Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2006 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 com.android.server;
     18 
     19 import com.android.internal.app.IMediaContainerService;
     20 import com.android.internal.app.ResolverActivity;
     21 import com.android.internal.content.PackageHelper;
     22 import com.android.internal.util.FastXmlSerializer;
     23 import com.android.internal.util.JournaledFile;
     24 import com.android.internal.util.XmlUtils;
     25 
     26 import org.xmlpull.v1.XmlPullParser;
     27 import org.xmlpull.v1.XmlPullParserException;
     28 import org.xmlpull.v1.XmlSerializer;
     29 
     30 import android.app.ActivityManagerNative;
     31 import android.app.IActivityManager;
     32 import android.app.admin.IDevicePolicyManager;
     33 import android.app.backup.IBackupManager;
     34 import android.content.Context;
     35 import android.content.ComponentName;
     36 import android.content.IIntentReceiver;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.content.IntentSender;
     40 import android.content.ServiceConnection;
     41 import android.content.IntentSender.SendIntentException;
     42 import android.content.pm.ActivityInfo;
     43 import android.content.pm.ApplicationInfo;
     44 import android.content.pm.ComponentInfo;
     45 import android.content.pm.FeatureInfo;
     46 import android.content.pm.IPackageDataObserver;
     47 import android.content.pm.IPackageDeleteObserver;
     48 import android.content.pm.IPackageInstallObserver;
     49 import android.content.pm.IPackageManager;
     50 import android.content.pm.IPackageMoveObserver;
     51 import android.content.pm.IPackageStatsObserver;
     52 import android.content.pm.InstrumentationInfo;
     53 import android.content.pm.PackageInfo;
     54 import android.content.pm.PackageInfoLite;
     55 import android.content.pm.PackageManager;
     56 import android.content.pm.PackageStats;
     57 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     58 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
     59 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
     60 import android.content.pm.PackageParser;
     61 import android.content.pm.PermissionInfo;
     62 import android.content.pm.PermissionGroupInfo;
     63 import android.content.pm.ProviderInfo;
     64 import android.content.pm.ResolveInfo;
     65 import android.content.pm.ServiceInfo;
     66 import android.content.pm.Signature;
     67 import android.net.Uri;
     68 import android.os.Binder;
     69 import android.os.Build;
     70 import android.os.Bundle;
     71 import android.os.Debug;
     72 import android.os.HandlerThread;
     73 import android.os.IBinder;
     74 import android.os.Looper;
     75 import android.os.Message;
     76 import android.os.Parcel;
     77 import android.os.RemoteException;
     78 import android.os.Environment;
     79 import android.os.FileObserver;
     80 import android.os.FileUtils;
     81 import android.os.Handler;
     82 import android.os.ParcelFileDescriptor;
     83 import android.os.Process;
     84 import android.os.ServiceManager;
     85 import android.os.SystemClock;
     86 import android.os.SystemProperties;
     87 import android.provider.Settings;
     88 import android.security.SystemKeyStore;
     89 import android.util.*;
     90 import android.view.Display;
     91 import android.view.WindowManager;
     92 
     93 import java.io.File;
     94 import java.io.FileDescriptor;
     95 import java.io.FileInputStream;
     96 import java.io.FileNotFoundException;
     97 import java.io.FileOutputStream;
     98 import java.io.FileReader;
     99 import java.io.FilenameFilter;
    100 import java.io.IOException;
    101 import java.io.InputStream;
    102 import java.io.PrintWriter;
    103 import java.security.NoSuchAlgorithmException;
    104 import java.text.SimpleDateFormat;
    105 import java.util.ArrayList;
    106 import java.util.Arrays;
    107 import java.util.Collection;
    108 import java.util.Collections;
    109 import java.util.Comparator;
    110 import java.util.Date;
    111 import java.util.Enumeration;
    112 import java.util.HashMap;
    113 import java.util.HashSet;
    114 import java.util.Iterator;
    115 import java.util.List;
    116 import java.util.Map;
    117 import java.util.Set;
    118 import java.util.zip.ZipEntry;
    119 import java.util.zip.ZipException;
    120 import java.util.zip.ZipFile;
    121 import java.util.zip.ZipOutputStream;
    122 
    123 /**
    124  * Keep track of all those .apks everywhere.
    125  *
    126  * This is very central to the platform's security; please run the unit
    127  * tests whenever making modifications here:
    128  *
    129 mmm frameworks/base/tests/AndroidTests
    130 adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
    131 adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
    132  *
    133  */
    134 class PackageManagerService extends IPackageManager.Stub {
    135     private static final String TAG = "PackageManager";
    136     private static final boolean DEBUG_SETTINGS = false;
    137     private static final boolean DEBUG_PREFERRED = false;
    138     private static final boolean DEBUG_UPGRADE = false;
    139     private static final boolean DEBUG_INSTALL = false;
    140     private static final boolean DEBUG_NATIVE = false;
    141 
    142     private static final boolean MULTIPLE_APPLICATION_UIDS = true;
    143     private static final int RADIO_UID = Process.PHONE_UID;
    144     private static final int LOG_UID = Process.LOG_UID;
    145     private static final int FIRST_APPLICATION_UID =
    146         Process.FIRST_APPLICATION_UID;
    147     private static final int MAX_APPLICATION_UIDS = 1000;
    148 
    149     private static final boolean SHOW_INFO = false;
    150 
    151     private static final boolean GET_CERTIFICATES = true;
    152 
    153     private static final int REMOVE_EVENTS =
    154         FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
    155     private static final int ADD_EVENTS =
    156         FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
    157 
    158     private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
    159     // Suffix used during package installation when copying/moving
    160     // package apks to install directory.
    161     private static final String INSTALL_PACKAGE_SUFFIX = "-";
    162 
    163     /**
    164      * Indicates the state of installation. Used by PackageManager to
    165      * figure out incomplete installations. Say a package is being installed
    166      * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
    167      * the package installation is successful or unsuccesful lin which case
    168      * the PackageManager will no longer maintain state information associated
    169      * with the package. If some exception(like device freeze or battery being
    170      * pulled out) occurs during installation of a package, the PackageManager
    171      * needs this information to clean up the previously failed installation.
    172      */
    173     private static final int PKG_INSTALL_INCOMPLETE = 0;
    174     private static final int PKG_INSTALL_COMPLETE = 1;
    175 
    176     static final int SCAN_MONITOR = 1<<0;
    177     static final int SCAN_NO_DEX = 1<<1;
    178     static final int SCAN_FORCE_DEX = 1<<2;
    179     static final int SCAN_UPDATE_SIGNATURE = 1<<3;
    180     static final int SCAN_NEW_INSTALL = 1<<4;
    181     static final int SCAN_NO_PATHS = 1<<5;
    182 
    183     static final int REMOVE_CHATTY = 1<<16;
    184 
    185     static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
    186             "com.android.defcontainer",
    187             "com.android.defcontainer.DefaultContainerService");
    188 
    189     final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
    190             Process.THREAD_PRIORITY_BACKGROUND);
    191     final PackageHandler mHandler;
    192 
    193     final int mSdkVersion = Build.VERSION.SDK_INT;
    194     final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
    195             ? null : Build.VERSION.CODENAME;
    196 
    197     final Context mContext;
    198     final boolean mFactoryTest;
    199     final boolean mNoDexOpt;
    200     final DisplayMetrics mMetrics;
    201     final int mDefParseFlags;
    202     final String[] mSeparateProcesses;
    203 
    204     // This is where all application persistent data goes.
    205     final File mAppDataDir;
    206 
    207     // This is the object monitoring the framework dir.
    208     final FileObserver mFrameworkInstallObserver;
    209 
    210     // This is the object monitoring the system app dir.
    211     final FileObserver mSystemInstallObserver;
    212 
    213     // This is the object monitoring mAppInstallDir.
    214     final FileObserver mAppInstallObserver;
    215 
    216     // This is the object monitoring mDrmAppPrivateInstallDir.
    217     final FileObserver mDrmAppInstallObserver;
    218 
    219     // Used for priviledge escalation.  MUST NOT BE CALLED WITH mPackages
    220     // LOCK HELD.  Can be called with mInstallLock held.
    221     final Installer mInstaller;
    222 
    223     final File mFrameworkDir;
    224     final File mSystemAppDir;
    225     final File mAppInstallDir;
    226     final File mDalvikCacheDir;
    227 
    228     // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
    229     // apps.
    230     final File mDrmAppPrivateInstallDir;
    231 
    232     // ----------------------------------------------------------------
    233 
    234     // Lock for state used when installing and doing other long running
    235     // operations.  Methods that must be called with this lock held have
    236     // the prefix "LI".
    237     final Object mInstallLock = new Object();
    238 
    239     // These are the directories in the 3rd party applications installed dir
    240     // that we have currently loaded packages from.  Keys are the application's
    241     // installed zip file (absolute codePath), and values are Package.
    242     final HashMap<String, PackageParser.Package> mAppDirs =
    243             new HashMap<String, PackageParser.Package>();
    244 
    245     // Information for the parser to write more useful error messages.
    246     File mScanningPath;
    247     int mLastScanError;
    248 
    249     final int[] mOutPermissions = new int[3];
    250 
    251     // ----------------------------------------------------------------
    252 
    253     // Keys are String (package name), values are Package.  This also serves
    254     // as the lock for the global state.  Methods that must be called with
    255     // this lock held have the prefix "LP".
    256     final HashMap<String, PackageParser.Package> mPackages =
    257             new HashMap<String, PackageParser.Package>();
    258 
    259     final Settings mSettings;
    260     boolean mRestoredSettings;
    261 
    262     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
    263     int[] mGlobalGids;
    264 
    265     // These are the built-in uid -> permission mappings that were read from the
    266     // etc/permissions.xml file.
    267     final SparseArray<HashSet<String>> mSystemPermissions =
    268             new SparseArray<HashSet<String>>();
    269 
    270     // These are the built-in shared libraries that were read from the
    271     // etc/permissions.xml file.
    272     final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
    273 
    274     // Temporary for building the final shared libraries for an .apk.
    275     String[] mTmpSharedLibraries = null;
    276 
    277     // These are the features this devices supports that were read from the
    278     // etc/permissions.xml file.
    279     final HashMap<String, FeatureInfo> mAvailableFeatures =
    280             new HashMap<String, FeatureInfo>();
    281 
    282     // All available activities, for your resolving pleasure.
    283     final ActivityIntentResolver mActivities =
    284             new ActivityIntentResolver();
    285 
    286     // All available receivers, for your resolving pleasure.
    287     final ActivityIntentResolver mReceivers =
    288             new ActivityIntentResolver();
    289 
    290     // All available services, for your resolving pleasure.
    291     final ServiceIntentResolver mServices = new ServiceIntentResolver();
    292 
    293     // Keys are String (provider class name), values are Provider.
    294     final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
    295             new HashMap<ComponentName, PackageParser.Provider>();
    296 
    297     // Mapping from provider base names (first directory in content URI codePath)
    298     // to the provider information.
    299     final HashMap<String, PackageParser.Provider> mProviders =
    300             new HashMap<String, PackageParser.Provider>();
    301 
    302     // Mapping from instrumentation class names to info about them.
    303     final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
    304             new HashMap<ComponentName, PackageParser.Instrumentation>();
    305 
    306     // Mapping from permission names to info about them.
    307     final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
    308             new HashMap<String, PackageParser.PermissionGroup>();
    309 
    310     // Packages whose data we have transfered into another package, thus
    311     // should no longer exist.
    312     final HashSet<String> mTransferedPackages = new HashSet<String>();
    313 
    314     // Broadcast actions that are only available to the system.
    315     final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
    316 
    317     boolean mSystemReady;
    318     boolean mSafeMode;
    319     boolean mHasSystemUidErrors;
    320 
    321     ApplicationInfo mAndroidApplication;
    322     final ActivityInfo mResolveActivity = new ActivityInfo();
    323     final ResolveInfo mResolveInfo = new ResolveInfo();
    324     ComponentName mResolveComponentName;
    325     PackageParser.Package mPlatformPackage;
    326 
    327     // Set of pending broadcasts for aggregating enable/disable of components.
    328     final HashMap<String, ArrayList<String>> mPendingBroadcasts
    329             = new HashMap<String, ArrayList<String>>();
    330     // Service Connection to remote media container service to copy
    331     // package uri's from external media onto secure containers
    332     // or internal storage.
    333     private IMediaContainerService mContainerService = null;
    334 
    335     static final int SEND_PENDING_BROADCAST = 1;
    336     static final int MCS_BOUND = 3;
    337     static final int END_COPY = 4;
    338     static final int INIT_COPY = 5;
    339     static final int MCS_UNBIND = 6;
    340     static final int START_CLEANING_PACKAGE = 7;
    341     static final int FIND_INSTALL_LOC = 8;
    342     static final int POST_INSTALL = 9;
    343     static final int MCS_RECONNECT = 10;
    344     static final int MCS_GIVE_UP = 11;
    345     static final int UPDATED_MEDIA_STATUS = 12;
    346     static final int WRITE_SETTINGS = 13;
    347 
    348     static final int WRITE_SETTINGS_DELAY = 10*1000;  // 10 seconds
    349 
    350     // Delay time in millisecs
    351     static final int BROADCAST_DELAY = 10 * 1000;
    352     final private DefaultContainerConnection mDefContainerConn =
    353             new DefaultContainerConnection();
    354     class DefaultContainerConnection implements ServiceConnection {
    355         public void onServiceConnected(ComponentName name, IBinder service) {
    356             if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
    357             IMediaContainerService imcs =
    358                 IMediaContainerService.Stub.asInterface(service);
    359             mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
    360         }
    361 
    362         public void onServiceDisconnected(ComponentName name) {
    363             if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
    364         }
    365     };
    366 
    367     // Recordkeeping of restore-after-install operations that are currently in flight
    368     // between the Package Manager and the Backup Manager
    369     class PostInstallData {
    370         public InstallArgs args;
    371         public PackageInstalledInfo res;
    372 
    373         PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
    374             args = _a;
    375             res = _r;
    376         }
    377     };
    378     final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
    379     int mNextInstallToken = 1;  // nonzero; will be wrapped back to 1 when ++ overflows
    380 
    381     class PackageHandler extends Handler {
    382         private boolean mBound = false;
    383         final ArrayList<HandlerParams> mPendingInstalls =
    384             new ArrayList<HandlerParams>();
    385 
    386         private boolean connectToService() {
    387             if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
    388                     " DefaultContainerService");
    389             Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
    390             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    391             if (mContext.bindService(service, mDefContainerConn,
    392                     Context.BIND_AUTO_CREATE)) {
    393                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    394                 mBound = true;
    395                 return true;
    396             }
    397             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    398             return false;
    399         }
    400 
    401         private void disconnectService() {
    402             mContainerService = null;
    403             mBound = false;
    404             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    405             mContext.unbindService(mDefContainerConn);
    406             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    407         }
    408 
    409         PackageHandler(Looper looper) {
    410             super(looper);
    411         }
    412 
    413         public void handleMessage(Message msg) {
    414             try {
    415                 doHandleMessage(msg);
    416             } finally {
    417                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    418             }
    419         }
    420 
    421         void doHandleMessage(Message msg) {
    422             switch (msg.what) {
    423                 case INIT_COPY: {
    424                     if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
    425                     HandlerParams params = (HandlerParams) msg.obj;
    426                     int idx = mPendingInstalls.size();
    427                     if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
    428                     // If a bind was already initiated we dont really
    429                     // need to do anything. The pending install
    430                     // will be processed later on.
    431                     if (!mBound) {
    432                         // If this is the only one pending we might
    433                         // have to bind to the service again.
    434                         if (!connectToService()) {
    435                             Slog.e(TAG, "Failed to bind to media container service");
    436                             params.serviceError();
    437                             return;
    438                         } else {
    439                             // Once we bind to the service, the first
    440                             // pending request will be processed.
    441                             mPendingInstalls.add(idx, params);
    442                         }
    443                     } else {
    444                         mPendingInstalls.add(idx, params);
    445                         // Already bound to the service. Just make
    446                         // sure we trigger off processing the first request.
    447                         if (idx == 0) {
    448                             mHandler.sendEmptyMessage(MCS_BOUND);
    449                         }
    450                     }
    451                     break;
    452                 }
    453                 case MCS_BOUND: {
    454                     if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
    455                     if (msg.obj != null) {
    456                         mContainerService = (IMediaContainerService) msg.obj;
    457                     }
    458                     if (mContainerService == null) {
    459                         // Something seriously wrong. Bail out
    460                         Slog.e(TAG, "Cannot bind to media container service");
    461                         for (HandlerParams params : mPendingInstalls) {
    462                             mPendingInstalls.remove(0);
    463                             // Indicate service bind error
    464                             params.serviceError();
    465                         }
    466                         mPendingInstalls.clear();
    467                     } else if (mPendingInstalls.size() > 0) {
    468                         HandlerParams params = mPendingInstalls.get(0);
    469                         if (params != null) {
    470                             params.startCopy();
    471                         }
    472                     } else {
    473                         // Should never happen ideally.
    474                         Slog.w(TAG, "Empty queue");
    475                     }
    476                     break;
    477                 }
    478                 case MCS_RECONNECT : {
    479                     if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
    480                     if (mPendingInstalls.size() > 0) {
    481                         if (mBound) {
    482                             disconnectService();
    483                         }
    484                         if (!connectToService()) {
    485                             Slog.e(TAG, "Failed to bind to media container service");
    486                             for (HandlerParams params : mPendingInstalls) {
    487                                 mPendingInstalls.remove(0);
    488                                 // Indicate service bind error
    489                                 params.serviceError();
    490                             }
    491                             mPendingInstalls.clear();
    492                         }
    493                     }
    494                     break;
    495                 }
    496                 case MCS_UNBIND : {
    497                     if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
    498                     // Delete pending install
    499                     if (mPendingInstalls.size() > 0) {
    500                         mPendingInstalls.remove(0);
    501                     }
    502                     if (mPendingInstalls.size() == 0) {
    503                         if (mBound) {
    504                             disconnectService();
    505                         }
    506                     } else {
    507                         // There are more pending requests in queue.
    508                         // Just post MCS_BOUND message to trigger processing
    509                         // of next pending install.
    510                         mHandler.sendEmptyMessage(MCS_BOUND);
    511                     }
    512                     break;
    513                 }
    514                 case MCS_GIVE_UP: {
    515                     if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
    516                     HandlerParams params = mPendingInstalls.remove(0);
    517                     break;
    518                 }
    519                 case SEND_PENDING_BROADCAST : {
    520                     String packages[];
    521                     ArrayList components[];
    522                     int size = 0;
    523                     int uids[];
    524                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    525                     synchronized (mPackages) {
    526                         if (mPendingBroadcasts == null) {
    527                             return;
    528                         }
    529                         size = mPendingBroadcasts.size();
    530                         if (size <= 0) {
    531                             // Nothing to be done. Just return
    532                             return;
    533                         }
    534                         packages = new String[size];
    535                         components = new ArrayList[size];
    536                         uids = new int[size];
    537                         Iterator<HashMap.Entry<String, ArrayList<String>>>
    538                                 it = mPendingBroadcasts.entrySet().iterator();
    539                         int i = 0;
    540                         while (it.hasNext() && i < size) {
    541                             HashMap.Entry<String, ArrayList<String>> ent = it.next();
    542                             packages[i] = ent.getKey();
    543                             components[i] = ent.getValue();
    544                             PackageSetting ps = mSettings.mPackages.get(ent.getKey());
    545                             uids[i] = (ps != null) ? ps.userId : -1;
    546                             i++;
    547                         }
    548                         size = i;
    549                         mPendingBroadcasts.clear();
    550                     }
    551                     // Send broadcasts
    552                     for (int i = 0; i < size; i++) {
    553                         sendPackageChangedBroadcast(packages[i], true,
    554                                 (ArrayList<String>)components[i], uids[i]);
    555                     }
    556                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    557                     break;
    558                 }
    559                 case START_CLEANING_PACKAGE: {
    560                     String packageName = (String)msg.obj;
    561                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    562                     synchronized (mPackages) {
    563                         if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
    564                             mSettings.mPackagesToBeCleaned.add(packageName);
    565                         }
    566                     }
    567                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    568                     startCleaningPackages();
    569                 } break;
    570                 case POST_INSTALL: {
    571                     if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
    572                     PostInstallData data = mRunningInstalls.get(msg.arg1);
    573                     mRunningInstalls.delete(msg.arg1);
    574                     boolean deleteOld = false;
    575 
    576                     if (data != null) {
    577                         InstallArgs args = data.args;
    578                         PackageInstalledInfo res = data.res;
    579 
    580                         if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
    581                             res.removedInfo.sendBroadcast(false, true);
    582                             Bundle extras = new Bundle(1);
    583                             extras.putInt(Intent.EXTRA_UID, res.uid);
    584                             final boolean update = res.removedInfo.removedPackage != null;
    585                             if (update) {
    586                                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
    587                             }
    588                             sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
    589                                     res.pkg.applicationInfo.packageName,
    590                                     extras, null);
    591                             if (update) {
    592                                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
    593                                         res.pkg.applicationInfo.packageName,
    594                                         extras, null);
    595                             }
    596                             if (res.removedInfo.args != null) {
    597                                 // Remove the replaced package's older resources safely now
    598                                 deleteOld = true;
    599                             }
    600                         }
    601                         // Force a gc to clear up things
    602                         Runtime.getRuntime().gc();
    603                         // We delete after a gc for applications  on sdcard.
    604                         if (deleteOld) {
    605                             synchronized (mInstallLock) {
    606                                 res.removedInfo.args.doPostDeleteLI(true);
    607                             }
    608                         }
    609                         if (args.observer != null) {
    610                             try {
    611                                 args.observer.packageInstalled(res.name, res.returnCode);
    612                             } catch (RemoteException e) {
    613                                 Slog.i(TAG, "Observer no longer exists.");
    614                             }
    615                         }
    616                     } else {
    617                         Slog.e(TAG, "Bogus post-install token " + msg.arg1);
    618                     }
    619                 } break;
    620                 case UPDATED_MEDIA_STATUS: {
    621                     if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
    622                     boolean reportStatus = msg.arg1 == 1;
    623                     boolean doGc = msg.arg2 == 1;
    624                     if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
    625                     if (doGc) {
    626                         // Force a gc to clear up stale containers.
    627                         Runtime.getRuntime().gc();
    628                     }
    629                     if (msg.obj != null) {
    630                         Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj;
    631                         if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
    632                         // Unload containers
    633                         unloadAllContainers(args);
    634                     }
    635                     if (reportStatus) {
    636                         try {
    637                             if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
    638                             PackageHelper.getMountService().finishMediaUpdate();
    639                         } catch (RemoteException e) {
    640                             Log.e(TAG, "MountService not running?");
    641                         }
    642                     }
    643                 } break;
    644                 case WRITE_SETTINGS: {
    645                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    646                     synchronized (mPackages) {
    647                         removeMessages(WRITE_SETTINGS);
    648                         mSettings.writeLP();
    649                     }
    650                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    651                 } break;
    652             }
    653         }
    654     }
    655 
    656     void scheduleWriteSettingsLocked() {
    657         if (!mHandler.hasMessages(WRITE_SETTINGS)) {
    658             mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
    659         }
    660     }
    661 
    662     static boolean installOnSd(int flags) {
    663         if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
    664                 ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
    665             return false;
    666         }
    667         if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
    668             return true;
    669         }
    670         return false;
    671     }
    672 
    673     static boolean isFwdLocked(int flags) {
    674         if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
    675             return true;
    676         }
    677         return false;
    678     }
    679 
    680     public static final IPackageManager main(Context context, boolean factoryTest) {
    681         PackageManagerService m = new PackageManagerService(context, factoryTest);
    682         ServiceManager.addService("package", m);
    683         return m;
    684     }
    685 
    686     static String[] splitString(String str, char sep) {
    687         int count = 1;
    688         int i = 0;
    689         while ((i=str.indexOf(sep, i)) >= 0) {
    690             count++;
    691             i++;
    692         }
    693 
    694         String[] res = new String[count];
    695         i=0;
    696         count = 0;
    697         int lastI=0;
    698         while ((i=str.indexOf(sep, i)) >= 0) {
    699             res[count] = str.substring(lastI, i);
    700             count++;
    701             i++;
    702             lastI = i;
    703         }
    704         res[count] = str.substring(lastI, str.length());
    705         return res;
    706     }
    707 
    708     public PackageManagerService(Context context, boolean factoryTest) {
    709         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
    710                 SystemClock.uptimeMillis());
    711 
    712         if (mSdkVersion <= 0) {
    713             Slog.w(TAG, "**** ro.build.version.sdk not set!");
    714         }
    715 
    716         mContext = context;
    717         mFactoryTest = factoryTest;
    718         mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
    719         mMetrics = new DisplayMetrics();
    720         mSettings = new Settings();
    721         mSettings.addSharedUserLP("android.uid.system",
    722                 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
    723         mSettings.addSharedUserLP("android.uid.phone",
    724                 MULTIPLE_APPLICATION_UIDS
    725                         ? RADIO_UID : FIRST_APPLICATION_UID,
    726                 ApplicationInfo.FLAG_SYSTEM);
    727         mSettings.addSharedUserLP("android.uid.log",
    728                 MULTIPLE_APPLICATION_UIDS
    729                         ? LOG_UID : FIRST_APPLICATION_UID,
    730                 ApplicationInfo.FLAG_SYSTEM);
    731 
    732         String separateProcesses = SystemProperties.get("debug.separate_processes");
    733         if (separateProcesses != null && separateProcesses.length() > 0) {
    734             if ("*".equals(separateProcesses)) {
    735                 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
    736                 mSeparateProcesses = null;
    737                 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
    738             } else {
    739                 mDefParseFlags = 0;
    740                 mSeparateProcesses = separateProcesses.split(",");
    741                 Slog.w(TAG, "Running with debug.separate_processes: "
    742                         + separateProcesses);
    743             }
    744         } else {
    745             mDefParseFlags = 0;
    746             mSeparateProcesses = null;
    747         }
    748 
    749         Installer installer = new Installer();
    750         // Little hacky thing to check if installd is here, to determine
    751         // whether we are running on the simulator and thus need to take
    752         // care of building the /data file structure ourself.
    753         // (apparently the sim now has a working installer)
    754         if (installer.ping() && Process.supportsProcesses()) {
    755             mInstaller = installer;
    756         } else {
    757             mInstaller = null;
    758         }
    759 
    760         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
    761         Display d = wm.getDefaultDisplay();
    762         d.getMetrics(mMetrics);
    763 
    764         synchronized (mInstallLock) {
    765         synchronized (mPackages) {
    766             mHandlerThread.start();
    767             mHandler = new PackageHandler(mHandlerThread.getLooper());
    768 
    769             File dataDir = Environment.getDataDirectory();
    770             mAppDataDir = new File(dataDir, "data");
    771             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
    772 
    773             if (mInstaller == null) {
    774                 // Make sure these dirs exist, when we are running in
    775                 // the simulator.
    776                 // Make a wide-open directory for random misc stuff.
    777                 File miscDir = new File(dataDir, "misc");
    778                 miscDir.mkdirs();
    779                 mAppDataDir.mkdirs();
    780                 mDrmAppPrivateInstallDir.mkdirs();
    781             }
    782 
    783             readPermissions();
    784 
    785             mRestoredSettings = mSettings.readLP();
    786             long startTime = SystemClock.uptimeMillis();
    787 
    788             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
    789                     startTime);
    790 
    791             // Set flag to monitor and not change apk file paths when
    792             // scanning install directories.
    793             int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
    794             if (mNoDexOpt) {
    795                 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
    796                 scanMode |= SCAN_NO_DEX;
    797             }
    798 
    799             final HashSet<String> libFiles = new HashSet<String>();
    800 
    801             mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
    802             mDalvikCacheDir = new File(dataDir, "dalvik-cache");
    803 
    804             if (mInstaller != null) {
    805                 boolean didDexOpt = false;
    806 
    807                 /**
    808                  * Out of paranoia, ensure that everything in the boot class
    809                  * path has been dexed.
    810                  */
    811                 String bootClassPath = System.getProperty("java.boot.class.path");
    812                 if (bootClassPath != null) {
    813                     String[] paths = splitString(bootClassPath, ':');
    814                     for (int i=0; i<paths.length; i++) {
    815                         try {
    816                             if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
    817                                 libFiles.add(paths[i]);
    818                                 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
    819                                 didDexOpt = true;
    820                             }
    821                         } catch (FileNotFoundException e) {
    822                             Slog.w(TAG, "Boot class path not found: " + paths[i]);
    823                         } catch (IOException e) {
    824                             Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
    825                         }
    826                     }
    827                 } else {
    828                     Slog.w(TAG, "No BOOTCLASSPATH found!");
    829                 }
    830 
    831                 /**
    832                  * Also ensure all external libraries have had dexopt run on them.
    833                  */
    834                 if (mSharedLibraries.size() > 0) {
    835                     Iterator<String> libs = mSharedLibraries.values().iterator();
    836                     while (libs.hasNext()) {
    837                         String lib = libs.next();
    838                         try {
    839                             if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
    840                                 libFiles.add(lib);
    841                                 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
    842                                 didDexOpt = true;
    843                             }
    844                         } catch (FileNotFoundException e) {
    845                             Slog.w(TAG, "Library not found: " + lib);
    846                         } catch (IOException e) {
    847                             Slog.w(TAG, "Exception reading library: " + lib, e);
    848                         }
    849                     }
    850                 }
    851 
    852                 // Gross hack for now: we know this file doesn't contain any
    853                 // code, so don't dexopt it to avoid the resulting log spew.
    854                 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
    855 
    856                 /**
    857                  * And there are a number of commands implemented in Java, which
    858                  * we currently need to do the dexopt on so that they can be
    859                  * run from a non-root shell.
    860                  */
    861                 String[] frameworkFiles = mFrameworkDir.list();
    862                 if (frameworkFiles != null) {
    863                     for (int i=0; i<frameworkFiles.length; i++) {
    864                         File libPath = new File(mFrameworkDir, frameworkFiles[i]);
    865                         String path = libPath.getPath();
    866                         // Skip the file if we alrady did it.
    867                         if (libFiles.contains(path)) {
    868                             continue;
    869                         }
    870                         // Skip the file if it is not a type we want to dexopt.
    871                         if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
    872                             continue;
    873                         }
    874                         try {
    875                             if (dalvik.system.DexFile.isDexOptNeeded(path)) {
    876                                 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
    877                                 didDexOpt = true;
    878                             }
    879                         } catch (FileNotFoundException e) {
    880                             Slog.w(TAG, "Jar not found: " + path);
    881                         } catch (IOException e) {
    882                             Slog.w(TAG, "Exception reading jar: " + path, e);
    883                         }
    884                     }
    885                 }
    886 
    887                 if (didDexOpt) {
    888                     // If we had to do a dexopt of one of the previous
    889                     // things, then something on the system has changed.
    890                     // Consider this significant, and wipe away all other
    891                     // existing dexopt files to ensure we don't leave any
    892                     // dangling around.
    893                     String[] files = mDalvikCacheDir.list();
    894                     if (files != null) {
    895                         for (int i=0; i<files.length; i++) {
    896                             String fn = files[i];
    897                             if (fn.startsWith("data@app@")
    898                                     || fn.startsWith("data@app-private@")) {
    899                                 Slog.i(TAG, "Pruning dalvik file: " + fn);
    900                                 (new File(mDalvikCacheDir, fn)).delete();
    901                             }
    902                         }
    903                     }
    904                 }
    905             }
    906 
    907             // Find base frameworks (resource packages without code).
    908             mFrameworkInstallObserver = new AppDirObserver(
    909                 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
    910             mFrameworkInstallObserver.startWatching();
    911             scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
    912                     | PackageParser.PARSE_IS_SYSTEM_DIR,
    913                     scanMode | SCAN_NO_DEX);
    914 
    915             // Collect all system packages.
    916             mSystemAppDir = new File(Environment.getRootDirectory(), "app");
    917             mSystemInstallObserver = new AppDirObserver(
    918                 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
    919             mSystemInstallObserver.startWatching();
    920             scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
    921                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
    922 
    923             if (mInstaller != null) {
    924                 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
    925                 mInstaller.moveFiles();
    926             }
    927 
    928             // Prune any system packages that no longer exist.
    929             Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
    930             while (psit.hasNext()) {
    931                 PackageSetting ps = psit.next();
    932                 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
    933                         && !mPackages.containsKey(ps.name)
    934                         && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
    935                     psit.remove();
    936                     String msg = "System package " + ps.name
    937                             + " no longer exists; wiping its data";
    938                     reportSettingsProblem(Log.WARN, msg);
    939                     if (mInstaller != null) {
    940                         mInstaller.remove(ps.name);
    941                     }
    942                 }
    943             }
    944 
    945             mAppInstallDir = new File(dataDir, "app");
    946             if (mInstaller == null) {
    947                 // Make sure these dirs exist, when we are running in
    948                 // the simulator.
    949                 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
    950             }
    951             //look for any incomplete package installations
    952             ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
    953             //clean up list
    954             for(int i = 0; i < deletePkgsList.size(); i++) {
    955                 //clean up here
    956                 cleanupInstallFailedPackage(deletePkgsList.get(i));
    957             }
    958             //delete tmp files
    959             deleteTempPackageFiles();
    960 
    961             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
    962                     SystemClock.uptimeMillis());
    963             mAppInstallObserver = new AppDirObserver(
    964                 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
    965             mAppInstallObserver.startWatching();
    966             scanDirLI(mAppInstallDir, 0, scanMode);
    967 
    968             mDrmAppInstallObserver = new AppDirObserver(
    969                 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
    970             mDrmAppInstallObserver.startWatching();
    971             scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
    972 
    973             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
    974                     SystemClock.uptimeMillis());
    975             Slog.i(TAG, "Time to scan packages: "
    976                     + ((SystemClock.uptimeMillis()-startTime)/1000f)
    977                     + " seconds");
    978 
    979             // If the platform SDK has changed since the last time we booted,
    980             // we need to re-grant app permission to catch any new ones that
    981             // appear.  This is really a hack, and means that apps can in some
    982             // cases get permissions that the user didn't initially explicitly
    983             // allow...  it would be nice to have some better way to handle
    984             // this situation.
    985             final boolean regrantPermissions = mSettings.mInternalSdkPlatform
    986                     != mSdkVersion;
    987             if (regrantPermissions) Slog.i(TAG, "Platform changed from "
    988                     + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
    989                     + "; regranting permissions for internal storage");
    990             mSettings.mInternalSdkPlatform = mSdkVersion;
    991 
    992             updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions);
    993 
    994             mSettings.writeLP();
    995 
    996             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
    997                     SystemClock.uptimeMillis());
    998 
    999             // Now after opening every single application zip, make sure they
   1000             // are all flushed.  Not really needed, but keeps things nice and
   1001             // tidy.
   1002             Runtime.getRuntime().gc();
   1003         } // synchronized (mPackages)
   1004         } // synchronized (mInstallLock)
   1005     }
   1006 
   1007     @Override
   1008     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
   1009             throws RemoteException {
   1010         try {
   1011             return super.onTransact(code, data, reply, flags);
   1012         } catch (RuntimeException e) {
   1013             if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
   1014                 Slog.e(TAG, "Package Manager Crash", e);
   1015             }
   1016             throw e;
   1017         }
   1018     }
   1019 
   1020     void cleanupInstallFailedPackage(PackageSetting ps) {
   1021         Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
   1022         if (mInstaller != null) {
   1023             int retCode = mInstaller.remove(ps.name);
   1024             if (retCode < 0) {
   1025                 Slog.w(TAG, "Couldn't remove app data directory for package: "
   1026                            + ps.name + ", retcode=" + retCode);
   1027             }
   1028         } else {
   1029             //for emulator
   1030             PackageParser.Package pkg = mPackages.get(ps.name);
   1031             File dataDir = new File(pkg.applicationInfo.dataDir);
   1032             dataDir.delete();
   1033         }
   1034         if (ps.codePath != null) {
   1035             if (!ps.codePath.delete()) {
   1036                 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
   1037             }
   1038         }
   1039         if (ps.resourcePath != null) {
   1040             if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
   1041                 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
   1042             }
   1043         }
   1044         mSettings.removePackageLP(ps.name);
   1045     }
   1046 
   1047     void readPermissions() {
   1048         // Read permissions from .../etc/permission directory.
   1049         File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
   1050         if (!libraryDir.exists() || !libraryDir.isDirectory()) {
   1051             Slog.w(TAG, "No directory " + libraryDir + ", skipping");
   1052             return;
   1053         }
   1054         if (!libraryDir.canRead()) {
   1055             Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
   1056             return;
   1057         }
   1058 
   1059         // Iterate over the files in the directory and scan .xml files
   1060         for (File f : libraryDir.listFiles()) {
   1061             // We'll read platform.xml last
   1062             if (f.getPath().endsWith("etc/permissions/platform.xml")) {
   1063                 continue;
   1064             }
   1065 
   1066             if (!f.getPath().endsWith(".xml")) {
   1067                 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
   1068                 continue;
   1069             }
   1070             if (!f.canRead()) {
   1071                 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
   1072                 continue;
   1073             }
   1074 
   1075             readPermissionsFromXml(f);
   1076         }
   1077 
   1078         // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
   1079         final File permFile = new File(Environment.getRootDirectory(),
   1080                 "etc/permissions/platform.xml");
   1081         readPermissionsFromXml(permFile);
   1082 
   1083         StringBuilder sb = new StringBuilder(128);
   1084         sb.append("Libs:");
   1085         Iterator<String> it = mSharedLibraries.keySet().iterator();
   1086         while (it.hasNext()) {
   1087             sb.append(' ');
   1088             String name = it.next();
   1089             sb.append(name);
   1090             sb.append(':');
   1091             sb.append(mSharedLibraries.get(name));
   1092         }
   1093         Log.i(TAG, sb.toString());
   1094 
   1095         sb.setLength(0);
   1096         sb.append("Features:");
   1097         it = mAvailableFeatures.keySet().iterator();
   1098         while (it.hasNext()) {
   1099             sb.append(' ');
   1100             sb.append(it.next());
   1101         }
   1102         Log.i(TAG, sb.toString());
   1103     }
   1104 
   1105     private void readPermissionsFromXml(File permFile) {
   1106         FileReader permReader = null;
   1107         try {
   1108             permReader = new FileReader(permFile);
   1109         } catch (FileNotFoundException e) {
   1110             Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
   1111             return;
   1112         }
   1113 
   1114         try {
   1115             XmlPullParser parser = Xml.newPullParser();
   1116             parser.setInput(permReader);
   1117 
   1118             XmlUtils.beginDocument(parser, "permissions");
   1119 
   1120             while (true) {
   1121                 XmlUtils.nextElement(parser);
   1122                 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
   1123                     break;
   1124                 }
   1125 
   1126                 String name = parser.getName();
   1127                 if ("group".equals(name)) {
   1128                     String gidStr = parser.getAttributeValue(null, "gid");
   1129                     if (gidStr != null) {
   1130                         int gid = Integer.parseInt(gidStr);
   1131                         mGlobalGids = appendInt(mGlobalGids, gid);
   1132                     } else {
   1133                         Slog.w(TAG, "<group> without gid at "
   1134                                 + parser.getPositionDescription());
   1135                     }
   1136 
   1137                     XmlUtils.skipCurrentTag(parser);
   1138                     continue;
   1139                 } else if ("permission".equals(name)) {
   1140                     String perm = parser.getAttributeValue(null, "name");
   1141                     if (perm == null) {
   1142                         Slog.w(TAG, "<permission> without name at "
   1143                                 + parser.getPositionDescription());
   1144                         XmlUtils.skipCurrentTag(parser);
   1145                         continue;
   1146                     }
   1147                     perm = perm.intern();
   1148                     readPermission(parser, perm);
   1149 
   1150                 } else if ("assign-permission".equals(name)) {
   1151                     String perm = parser.getAttributeValue(null, "name");
   1152                     if (perm == null) {
   1153                         Slog.w(TAG, "<assign-permission> without name at "
   1154                                 + parser.getPositionDescription());
   1155                         XmlUtils.skipCurrentTag(parser);
   1156                         continue;
   1157                     }
   1158                     String uidStr = parser.getAttributeValue(null, "uid");
   1159                     if (uidStr == null) {
   1160                         Slog.w(TAG, "<assign-permission> without uid at "
   1161                                 + parser.getPositionDescription());
   1162                         XmlUtils.skipCurrentTag(parser);
   1163                         continue;
   1164                     }
   1165                     int uid = Process.getUidForName(uidStr);
   1166                     if (uid < 0) {
   1167                         Slog.w(TAG, "<assign-permission> with unknown uid \""
   1168                                 + uidStr + "\" at "
   1169                                 + parser.getPositionDescription());
   1170                         XmlUtils.skipCurrentTag(parser);
   1171                         continue;
   1172                     }
   1173                     perm = perm.intern();
   1174                     HashSet<String> perms = mSystemPermissions.get(uid);
   1175                     if (perms == null) {
   1176                         perms = new HashSet<String>();
   1177                         mSystemPermissions.put(uid, perms);
   1178                     }
   1179                     perms.add(perm);
   1180                     XmlUtils.skipCurrentTag(parser);
   1181 
   1182                 } else if ("library".equals(name)) {
   1183                     String lname = parser.getAttributeValue(null, "name");
   1184                     String lfile = parser.getAttributeValue(null, "file");
   1185                     if (lname == null) {
   1186                         Slog.w(TAG, "<library> without name at "
   1187                                 + parser.getPositionDescription());
   1188                     } else if (lfile == null) {
   1189                         Slog.w(TAG, "<library> without file at "
   1190                                 + parser.getPositionDescription());
   1191                     } else {
   1192                         //Log.i(TAG, "Got library " + lname + " in " + lfile);
   1193                         mSharedLibraries.put(lname, lfile);
   1194                     }
   1195                     XmlUtils.skipCurrentTag(parser);
   1196                     continue;
   1197 
   1198                 } else if ("feature".equals(name)) {
   1199                     String fname = parser.getAttributeValue(null, "name");
   1200                     if (fname == null) {
   1201                         Slog.w(TAG, "<feature> without name at "
   1202                                 + parser.getPositionDescription());
   1203                     } else {
   1204                         //Log.i(TAG, "Got feature " + fname);
   1205                         FeatureInfo fi = new FeatureInfo();
   1206                         fi.name = fname;
   1207                         mAvailableFeatures.put(fname, fi);
   1208                     }
   1209                     XmlUtils.skipCurrentTag(parser);
   1210                     continue;
   1211 
   1212                 } else {
   1213                     XmlUtils.skipCurrentTag(parser);
   1214                     continue;
   1215                 }
   1216 
   1217             }
   1218         } catch (XmlPullParserException e) {
   1219             Slog.w(TAG, "Got execption parsing permissions.", e);
   1220         } catch (IOException e) {
   1221             Slog.w(TAG, "Got execption parsing permissions.", e);
   1222         }
   1223     }
   1224 
   1225     void readPermission(XmlPullParser parser, String name)
   1226             throws IOException, XmlPullParserException {
   1227 
   1228         name = name.intern();
   1229 
   1230         BasePermission bp = mSettings.mPermissions.get(name);
   1231         if (bp == null) {
   1232             bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
   1233             mSettings.mPermissions.put(name, bp);
   1234         }
   1235         int outerDepth = parser.getDepth();
   1236         int type;
   1237         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   1238                && (type != XmlPullParser.END_TAG
   1239                        || parser.getDepth() > outerDepth)) {
   1240             if (type == XmlPullParser.END_TAG
   1241                     || type == XmlPullParser.TEXT) {
   1242                 continue;
   1243             }
   1244 
   1245             String tagName = parser.getName();
   1246             if ("group".equals(tagName)) {
   1247                 String gidStr = parser.getAttributeValue(null, "gid");
   1248                 if (gidStr != null) {
   1249                     int gid = Process.getGidForName(gidStr);
   1250                     bp.gids = appendInt(bp.gids, gid);
   1251                 } else {
   1252                     Slog.w(TAG, "<group> without gid at "
   1253                             + parser.getPositionDescription());
   1254                 }
   1255             }
   1256             XmlUtils.skipCurrentTag(parser);
   1257         }
   1258     }
   1259 
   1260     static int[] appendInt(int[] cur, int val) {
   1261         if (cur == null) {
   1262             return new int[] { val };
   1263         }
   1264         final int N = cur.length;
   1265         for (int i=0; i<N; i++) {
   1266             if (cur[i] == val) {
   1267                 return cur;
   1268             }
   1269         }
   1270         int[] ret = new int[N+1];
   1271         System.arraycopy(cur, 0, ret, 0, N);
   1272         ret[N] = val;
   1273         return ret;
   1274     }
   1275 
   1276     static int[] appendInts(int[] cur, int[] add) {
   1277         if (add == null) return cur;
   1278         if (cur == null) return add;
   1279         final int N = add.length;
   1280         for (int i=0; i<N; i++) {
   1281             cur = appendInt(cur, add[i]);
   1282         }
   1283         return cur;
   1284     }
   1285 
   1286     static int[] removeInt(int[] cur, int val) {
   1287         if (cur == null) {
   1288             return null;
   1289         }
   1290         final int N = cur.length;
   1291         for (int i=0; i<N; i++) {
   1292             if (cur[i] == val) {
   1293                 int[] ret = new int[N-1];
   1294                 if (i > 0) {
   1295                     System.arraycopy(cur, 0, ret, 0, i);
   1296                 }
   1297                 if (i < (N-1)) {
   1298                     System.arraycopy(cur, i + 1, ret, i, N - i - 1);
   1299                 }
   1300                 return ret;
   1301             }
   1302         }
   1303         return cur;
   1304     }
   1305 
   1306     static int[] removeInts(int[] cur, int[] rem) {
   1307         if (rem == null) return cur;
   1308         if (cur == null) return cur;
   1309         final int N = rem.length;
   1310         for (int i=0; i<N; i++) {
   1311             cur = removeInt(cur, rem[i]);
   1312         }
   1313         return cur;
   1314     }
   1315 
   1316     PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
   1317         if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
   1318             // The package has been uninstalled but has retained data and resources.
   1319             return PackageParser.generatePackageInfo(p, null, flags);
   1320         }
   1321         final PackageSetting ps = (PackageSetting)p.mExtras;
   1322         if (ps == null) {
   1323             return null;
   1324         }
   1325         final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
   1326         return PackageParser.generatePackageInfo(p, gp.gids, flags);
   1327     }
   1328 
   1329     public PackageInfo getPackageInfo(String packageName, int flags) {
   1330         synchronized (mPackages) {
   1331             PackageParser.Package p = mPackages.get(packageName);
   1332             if (Config.LOGV) Log.v(
   1333                 TAG, "getPackageInfo " + packageName
   1334                 + ": " + p);
   1335             if (p != null) {
   1336                 return generatePackageInfo(p, flags);
   1337             }
   1338             if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
   1339                 return generatePackageInfoFromSettingsLP(packageName, flags);
   1340             }
   1341         }
   1342         return null;
   1343     }
   1344 
   1345     public String[] currentToCanonicalPackageNames(String[] names) {
   1346         String[] out = new String[names.length];
   1347         synchronized (mPackages) {
   1348             for (int i=names.length-1; i>=0; i--) {
   1349                 PackageSetting ps = mSettings.mPackages.get(names[i]);
   1350                 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
   1351             }
   1352         }
   1353         return out;
   1354     }
   1355 
   1356     public String[] canonicalToCurrentPackageNames(String[] names) {
   1357         String[] out = new String[names.length];
   1358         synchronized (mPackages) {
   1359             for (int i=names.length-1; i>=0; i--) {
   1360                 String cur = mSettings.mRenamedPackages.get(names[i]);
   1361                 out[i] = cur != null ? cur : names[i];
   1362             }
   1363         }
   1364         return out;
   1365     }
   1366 
   1367     public int getPackageUid(String packageName) {
   1368         synchronized (mPackages) {
   1369             PackageParser.Package p = mPackages.get(packageName);
   1370             if(p != null) {
   1371                 return p.applicationInfo.uid;
   1372             }
   1373             PackageSetting ps = mSettings.mPackages.get(packageName);
   1374             if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
   1375                 return -1;
   1376             }
   1377             p = ps.pkg;
   1378             return p != null ? p.applicationInfo.uid : -1;
   1379         }
   1380     }
   1381 
   1382     public int[] getPackageGids(String packageName) {
   1383         synchronized (mPackages) {
   1384             PackageParser.Package p = mPackages.get(packageName);
   1385             if (Config.LOGV) Log.v(
   1386                 TAG, "getPackageGids" + packageName
   1387                 + ": " + p);
   1388             if (p != null) {
   1389                 final PackageSetting ps = (PackageSetting)p.mExtras;
   1390                 final SharedUserSetting suid = ps.sharedUser;
   1391                 return suid != null ? suid.gids : ps.gids;
   1392             }
   1393         }
   1394         // stupid thing to indicate an error.
   1395         return new int[0];
   1396     }
   1397 
   1398     static final PermissionInfo generatePermissionInfo(
   1399             BasePermission bp, int flags) {
   1400         if (bp.perm != null) {
   1401             return PackageParser.generatePermissionInfo(bp.perm, flags);
   1402         }
   1403         PermissionInfo pi = new PermissionInfo();
   1404         pi.name = bp.name;
   1405         pi.packageName = bp.sourcePackage;
   1406         pi.nonLocalizedLabel = bp.name;
   1407         pi.protectionLevel = bp.protectionLevel;
   1408         return pi;
   1409     }
   1410 
   1411     public PermissionInfo getPermissionInfo(String name, int flags) {
   1412         synchronized (mPackages) {
   1413             final BasePermission p = mSettings.mPermissions.get(name);
   1414             if (p != null) {
   1415                 return generatePermissionInfo(p, flags);
   1416             }
   1417             return null;
   1418         }
   1419     }
   1420 
   1421     public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
   1422         synchronized (mPackages) {
   1423             ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
   1424             for (BasePermission p : mSettings.mPermissions.values()) {
   1425                 if (group == null) {
   1426                     if (p.perm == null || p.perm.info.group == null) {
   1427                         out.add(generatePermissionInfo(p, flags));
   1428                     }
   1429                 } else {
   1430                     if (p.perm != null && group.equals(p.perm.info.group)) {
   1431                         out.add(PackageParser.generatePermissionInfo(p.perm, flags));
   1432                     }
   1433                 }
   1434             }
   1435 
   1436             if (out.size() > 0) {
   1437                 return out;
   1438             }
   1439             return mPermissionGroups.containsKey(group) ? out : null;
   1440         }
   1441     }
   1442 
   1443     public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
   1444         synchronized (mPackages) {
   1445             return PackageParser.generatePermissionGroupInfo(
   1446                     mPermissionGroups.get(name), flags);
   1447         }
   1448     }
   1449 
   1450     public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
   1451         synchronized (mPackages) {
   1452             final int N = mPermissionGroups.size();
   1453             ArrayList<PermissionGroupInfo> out
   1454                     = new ArrayList<PermissionGroupInfo>(N);
   1455             for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
   1456                 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
   1457             }
   1458             return out;
   1459         }
   1460     }
   1461 
   1462     private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
   1463         PackageSetting ps = mSettings.mPackages.get(packageName);
   1464         if(ps != null) {
   1465             if(ps.pkg == null) {
   1466                 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
   1467                 if(pInfo != null) {
   1468                     return pInfo.applicationInfo;
   1469                 }
   1470                 return null;
   1471             }
   1472             return PackageParser.generateApplicationInfo(ps.pkg, flags);
   1473         }
   1474         return null;
   1475     }
   1476 
   1477     private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
   1478         PackageSetting ps = mSettings.mPackages.get(packageName);
   1479         if(ps != null) {
   1480             if(ps.pkg == null) {
   1481                 ps.pkg = new PackageParser.Package(packageName);
   1482                 ps.pkg.applicationInfo.packageName = packageName;
   1483                 ps.pkg.applicationInfo.flags = ps.pkgFlags;
   1484                 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
   1485                 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
   1486                 ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
   1487             }
   1488             return generatePackageInfo(ps.pkg, flags);
   1489         }
   1490         return null;
   1491     }
   1492 
   1493     public ApplicationInfo getApplicationInfo(String packageName, int flags) {
   1494         synchronized (mPackages) {
   1495             PackageParser.Package p = mPackages.get(packageName);
   1496             if (Config.LOGV) Log.v(
   1497                     TAG, "getApplicationInfo " + packageName
   1498                     + ": " + p);
   1499             if (p != null) {
   1500                 // Note: isEnabledLP() does not apply here - always return info
   1501                 return PackageParser.generateApplicationInfo(p, flags);
   1502             }
   1503             if ("android".equals(packageName)||"system".equals(packageName)) {
   1504                 return mAndroidApplication;
   1505             }
   1506             if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
   1507                 return generateApplicationInfoFromSettingsLP(packageName, flags);
   1508             }
   1509         }
   1510         return null;
   1511     }
   1512 
   1513 
   1514     public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
   1515         mContext.enforceCallingOrSelfPermission(
   1516                 android.Manifest.permission.CLEAR_APP_CACHE, null);
   1517         // Queue up an async operation since clearing cache may take a little while.
   1518         mHandler.post(new Runnable() {
   1519             public void run() {
   1520                 mHandler.removeCallbacks(this);
   1521                 int retCode = -1;
   1522                 if (mInstaller != null) {
   1523                     retCode = mInstaller.freeCache(freeStorageSize);
   1524                     if (retCode < 0) {
   1525                         Slog.w(TAG, "Couldn't clear application caches");
   1526                     }
   1527                 } //end if mInstaller
   1528                 if (observer != null) {
   1529                     try {
   1530                         observer.onRemoveCompleted(null, (retCode >= 0));
   1531                     } catch (RemoteException e) {
   1532                         Slog.w(TAG, "RemoveException when invoking call back");
   1533                     }
   1534                 }
   1535             }
   1536         });
   1537     }
   1538 
   1539     public void freeStorage(final long freeStorageSize, final IntentSender pi) {
   1540         mContext.enforceCallingOrSelfPermission(
   1541                 android.Manifest.permission.CLEAR_APP_CACHE, null);
   1542         // Queue up an async operation since clearing cache may take a little while.
   1543         mHandler.post(new Runnable() {
   1544             public void run() {
   1545                 mHandler.removeCallbacks(this);
   1546                 int retCode = -1;
   1547                 if (mInstaller != null) {
   1548                     retCode = mInstaller.freeCache(freeStorageSize);
   1549                     if (retCode < 0) {
   1550                         Slog.w(TAG, "Couldn't clear application caches");
   1551                     }
   1552                 }
   1553                 if(pi != null) {
   1554                     try {
   1555                         // Callback via pending intent
   1556                         int code = (retCode >= 0) ? 1 : 0;
   1557                         pi.sendIntent(null, code, null,
   1558                                 null, null);
   1559                     } catch (SendIntentException e1) {
   1560                         Slog.i(TAG, "Failed to send pending intent");
   1561                     }
   1562                 }
   1563             }
   1564         });
   1565     }
   1566 
   1567     public ActivityInfo getActivityInfo(ComponentName component, int flags) {
   1568         synchronized (mPackages) {
   1569             PackageParser.Activity a = mActivities.mActivities.get(component);
   1570 
   1571             if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
   1572             if (a != null && mSettings.isEnabledLP(a.info, flags)) {
   1573                 return PackageParser.generateActivityInfo(a, flags);
   1574             }
   1575             if (mResolveComponentName.equals(component)) {
   1576                 return mResolveActivity;
   1577             }
   1578         }
   1579         return null;
   1580     }
   1581 
   1582     public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
   1583         synchronized (mPackages) {
   1584             PackageParser.Activity a = mReceivers.mActivities.get(component);
   1585             if (Config.LOGV) Log.v(
   1586                 TAG, "getReceiverInfo " + component + ": " + a);
   1587             if (a != null && mSettings.isEnabledLP(a.info, flags)) {
   1588                 return PackageParser.generateActivityInfo(a, flags);
   1589             }
   1590         }
   1591         return null;
   1592     }
   1593 
   1594     public ServiceInfo getServiceInfo(ComponentName component, int flags) {
   1595         synchronized (mPackages) {
   1596             PackageParser.Service s = mServices.mServices.get(component);
   1597             if (Config.LOGV) Log.v(
   1598                 TAG, "getServiceInfo " + component + ": " + s);
   1599             if (s != null && mSettings.isEnabledLP(s.info, flags)) {
   1600                 return PackageParser.generateServiceInfo(s, flags);
   1601             }
   1602         }
   1603         return null;
   1604     }
   1605 
   1606     public String[] getSystemSharedLibraryNames() {
   1607         Set<String> libSet;
   1608         synchronized (mPackages) {
   1609             libSet = mSharedLibraries.keySet();
   1610             int size = libSet.size();
   1611             if (size > 0) {
   1612                 String[] libs = new String[size];
   1613                 libSet.toArray(libs);
   1614                 return libs;
   1615             }
   1616         }
   1617         return null;
   1618     }
   1619 
   1620     public FeatureInfo[] getSystemAvailableFeatures() {
   1621         Collection<FeatureInfo> featSet;
   1622         synchronized (mPackages) {
   1623             featSet = mAvailableFeatures.values();
   1624             int size = featSet.size();
   1625             if (size > 0) {
   1626                 FeatureInfo[] features = new FeatureInfo[size+1];
   1627                 featSet.toArray(features);
   1628                 FeatureInfo fi = new FeatureInfo();
   1629                 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
   1630                         FeatureInfo.GL_ES_VERSION_UNDEFINED);
   1631                 features[size] = fi;
   1632                 return features;
   1633             }
   1634         }
   1635         return null;
   1636     }
   1637 
   1638     public boolean hasSystemFeature(String name) {
   1639         synchronized (mPackages) {
   1640             return mAvailableFeatures.containsKey(name);
   1641         }
   1642     }
   1643 
   1644     public int checkPermission(String permName, String pkgName) {
   1645         synchronized (mPackages) {
   1646             PackageParser.Package p = mPackages.get(pkgName);
   1647             if (p != null && p.mExtras != null) {
   1648                 PackageSetting ps = (PackageSetting)p.mExtras;
   1649                 if (ps.sharedUser != null) {
   1650                     if (ps.sharedUser.grantedPermissions.contains(permName)) {
   1651                         return PackageManager.PERMISSION_GRANTED;
   1652                     }
   1653                 } else if (ps.grantedPermissions.contains(permName)) {
   1654                     return PackageManager.PERMISSION_GRANTED;
   1655                 }
   1656             }
   1657         }
   1658         return PackageManager.PERMISSION_DENIED;
   1659     }
   1660 
   1661     public int checkUidPermission(String permName, int uid) {
   1662         synchronized (mPackages) {
   1663             Object obj = mSettings.getUserIdLP(uid);
   1664             if (obj != null) {
   1665                 GrantedPermissions gp = (GrantedPermissions)obj;
   1666                 if (gp.grantedPermissions.contains(permName)) {
   1667                     return PackageManager.PERMISSION_GRANTED;
   1668                 }
   1669             } else {
   1670                 HashSet<String> perms = mSystemPermissions.get(uid);
   1671                 if (perms != null && perms.contains(permName)) {
   1672                     return PackageManager.PERMISSION_GRANTED;
   1673                 }
   1674             }
   1675         }
   1676         return PackageManager.PERMISSION_DENIED;
   1677     }
   1678 
   1679     private BasePermission findPermissionTreeLP(String permName) {
   1680         for(BasePermission bp : mSettings.mPermissionTrees.values()) {
   1681             if (permName.startsWith(bp.name) &&
   1682                     permName.length() > bp.name.length() &&
   1683                     permName.charAt(bp.name.length()) == '.') {
   1684                 return bp;
   1685             }
   1686         }
   1687         return null;
   1688     }
   1689 
   1690     private BasePermission checkPermissionTreeLP(String permName) {
   1691         if (permName != null) {
   1692             BasePermission bp = findPermissionTreeLP(permName);
   1693             if (bp != null) {
   1694                 if (bp.uid == Binder.getCallingUid()) {
   1695                     return bp;
   1696                 }
   1697                 throw new SecurityException("Calling uid "
   1698                         + Binder.getCallingUid()
   1699                         + " is not allowed to add to permission tree "
   1700                         + bp.name + " owned by uid " + bp.uid);
   1701             }
   1702         }
   1703         throw new SecurityException("No permission tree found for " + permName);
   1704     }
   1705 
   1706     static boolean compareStrings(CharSequence s1, CharSequence s2) {
   1707         if (s1 == null) {
   1708             return s2 == null;
   1709         }
   1710         if (s2 == null) {
   1711             return false;
   1712         }
   1713         if (s1.getClass() != s2.getClass()) {
   1714             return false;
   1715         }
   1716         return s1.equals(s2);
   1717     }
   1718 
   1719     static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
   1720         if (pi1.icon != pi2.icon) return false;
   1721         if (pi1.protectionLevel != pi2.protectionLevel) return false;
   1722         if (!compareStrings(pi1.name, pi2.name)) return false;
   1723         if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
   1724         // We'll take care of setting this one.
   1725         if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
   1726         // These are not currently stored in settings.
   1727         //if (!compareStrings(pi1.group, pi2.group)) return false;
   1728         //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
   1729         //if (pi1.labelRes != pi2.labelRes) return false;
   1730         //if (pi1.descriptionRes != pi2.descriptionRes) return false;
   1731         return true;
   1732     }
   1733 
   1734     boolean addPermissionLocked(PermissionInfo info, boolean async) {
   1735         if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
   1736             throw new SecurityException("Label must be specified in permission");
   1737         }
   1738         BasePermission tree = checkPermissionTreeLP(info.name);
   1739         BasePermission bp = mSettings.mPermissions.get(info.name);
   1740         boolean added = bp == null;
   1741         boolean changed = true;
   1742         if (added) {
   1743             bp = new BasePermission(info.name, tree.sourcePackage,
   1744                     BasePermission.TYPE_DYNAMIC);
   1745         } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
   1746             throw new SecurityException(
   1747                     "Not allowed to modify non-dynamic permission "
   1748                     + info.name);
   1749         } else {
   1750             if (bp.protectionLevel == info.protectionLevel
   1751                     && bp.perm.owner.equals(tree.perm.owner)
   1752                     && bp.uid == tree.uid
   1753                     && comparePermissionInfos(bp.perm.info, info)) {
   1754                 changed = false;
   1755             }
   1756         }
   1757         bp.protectionLevel = info.protectionLevel;
   1758         bp.perm = new PackageParser.Permission(tree.perm.owner,
   1759                 new PermissionInfo(info));
   1760         bp.perm.info.packageName = tree.perm.info.packageName;
   1761         bp.uid = tree.uid;
   1762         if (added) {
   1763             mSettings.mPermissions.put(info.name, bp);
   1764         }
   1765         if (changed) {
   1766             if (!async) {
   1767                 mSettings.writeLP();
   1768             } else {
   1769                 scheduleWriteSettingsLocked();
   1770             }
   1771         }
   1772         return added;
   1773     }
   1774 
   1775     public boolean addPermission(PermissionInfo info) {
   1776         synchronized (mPackages) {
   1777             return addPermissionLocked(info, false);
   1778         }
   1779     }
   1780 
   1781     public boolean addPermissionAsync(PermissionInfo info) {
   1782         synchronized (mPackages) {
   1783             return addPermissionLocked(info, true);
   1784         }
   1785     }
   1786 
   1787     public void removePermission(String name) {
   1788         synchronized (mPackages) {
   1789             checkPermissionTreeLP(name);
   1790             BasePermission bp = mSettings.mPermissions.get(name);
   1791             if (bp != null) {
   1792                 if (bp.type != BasePermission.TYPE_DYNAMIC) {
   1793                     throw new SecurityException(
   1794                             "Not allowed to modify non-dynamic permission "
   1795                             + name);
   1796                 }
   1797                 mSettings.mPermissions.remove(name);
   1798                 mSettings.writeLP();
   1799             }
   1800         }
   1801     }
   1802 
   1803     public boolean isProtectedBroadcast(String actionName) {
   1804         synchronized (mPackages) {
   1805             return mProtectedBroadcasts.contains(actionName);
   1806         }
   1807     }
   1808 
   1809     public int checkSignatures(String pkg1, String pkg2) {
   1810         synchronized (mPackages) {
   1811             PackageParser.Package p1 = mPackages.get(pkg1);
   1812             PackageParser.Package p2 = mPackages.get(pkg2);
   1813             if (p1 == null || p1.mExtras == null
   1814                     || p2 == null || p2.mExtras == null) {
   1815                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
   1816             }
   1817             return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
   1818         }
   1819     }
   1820 
   1821     public int checkUidSignatures(int uid1, int uid2) {
   1822         synchronized (mPackages) {
   1823             Signature[] s1;
   1824             Signature[] s2;
   1825             Object obj = mSettings.getUserIdLP(uid1);
   1826             if (obj != null) {
   1827                 if (obj instanceof SharedUserSetting) {
   1828                     s1 = ((SharedUserSetting)obj).signatures.mSignatures;
   1829                 } else if (obj instanceof PackageSetting) {
   1830                     s1 = ((PackageSetting)obj).signatures.mSignatures;
   1831                 } else {
   1832                     return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
   1833                 }
   1834             } else {
   1835                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
   1836             }
   1837             obj = mSettings.getUserIdLP(uid2);
   1838             if (obj != null) {
   1839                 if (obj instanceof SharedUserSetting) {
   1840                     s2 = ((SharedUserSetting)obj).signatures.mSignatures;
   1841                 } else if (obj instanceof PackageSetting) {
   1842                     s2 = ((PackageSetting)obj).signatures.mSignatures;
   1843                 } else {
   1844                     return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
   1845                 }
   1846             } else {
   1847                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
   1848             }
   1849             return checkSignaturesLP(s1, s2);
   1850         }
   1851     }
   1852 
   1853     int checkSignaturesLP(Signature[] s1, Signature[] s2) {
   1854         if (s1 == null) {
   1855             return s2 == null
   1856                     ? PackageManager.SIGNATURE_NEITHER_SIGNED
   1857                     : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
   1858         }
   1859         if (s2 == null) {
   1860             return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
   1861         }
   1862         HashSet<Signature> set1 = new HashSet<Signature>();
   1863         for (Signature sig : s1) {
   1864             set1.add(sig);
   1865         }
   1866         HashSet<Signature> set2 = new HashSet<Signature>();
   1867         for (Signature sig : s2) {
   1868             set2.add(sig);
   1869         }
   1870         // Make sure s2 contains all signatures in s1.
   1871         if (set1.equals(set2)) {
   1872             return PackageManager.SIGNATURE_MATCH;
   1873         }
   1874         return PackageManager.SIGNATURE_NO_MATCH;
   1875     }
   1876 
   1877     public String[] getPackagesForUid(int uid) {
   1878         synchronized (mPackages) {
   1879             Object obj = mSettings.getUserIdLP(uid);
   1880             if (obj instanceof SharedUserSetting) {
   1881                 SharedUserSetting sus = (SharedUserSetting)obj;
   1882                 final int N = sus.packages.size();
   1883                 String[] res = new String[N];
   1884                 Iterator<PackageSetting> it = sus.packages.iterator();
   1885                 int i=0;
   1886                 while (it.hasNext()) {
   1887                     res[i++] = it.next().name;
   1888                 }
   1889                 return res;
   1890             } else if (obj instanceof PackageSetting) {
   1891                 PackageSetting ps = (PackageSetting)obj;
   1892                 return new String[] { ps.name };
   1893             }
   1894         }
   1895         return null;
   1896     }
   1897 
   1898     public String getNameForUid(int uid) {
   1899         synchronized (mPackages) {
   1900             Object obj = mSettings.getUserIdLP(uid);
   1901             if (obj instanceof SharedUserSetting) {
   1902                 SharedUserSetting sus = (SharedUserSetting)obj;
   1903                 return sus.name + ":" + sus.userId;
   1904             } else if (obj instanceof PackageSetting) {
   1905                 PackageSetting ps = (PackageSetting)obj;
   1906                 return ps.name;
   1907             }
   1908         }
   1909         return null;
   1910     }
   1911 
   1912     public int getUidForSharedUser(String sharedUserName) {
   1913         if(sharedUserName == null) {
   1914             return -1;
   1915         }
   1916         synchronized (mPackages) {
   1917             SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
   1918             if(suid == null) {
   1919                 return -1;
   1920             }
   1921             return suid.userId;
   1922         }
   1923     }
   1924 
   1925     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
   1926             int flags) {
   1927         List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
   1928         return chooseBestActivity(intent, resolvedType, flags, query);
   1929     }
   1930 
   1931     private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
   1932                                            int flags, List<ResolveInfo> query) {
   1933         if (query != null) {
   1934             final int N = query.size();
   1935             if (N == 1) {
   1936                 return query.get(0);
   1937             } else if (N > 1) {
   1938                 // If there is more than one activity with the same priority,
   1939                 // then let the user decide between them.
   1940                 ResolveInfo r0 = query.get(0);
   1941                 ResolveInfo r1 = query.get(1);
   1942                 if (false) {
   1943                     System.out.println(r0.activityInfo.name +
   1944                                        "=" + r0.priority + " vs " +
   1945                                        r1.activityInfo.name +
   1946                                        "=" + r1.priority);
   1947                 }
   1948                 // If the first activity has a higher priority, or a different
   1949                 // default, then it is always desireable to pick it.
   1950                 if (r0.priority != r1.priority
   1951                         || r0.preferredOrder != r1.preferredOrder
   1952                         || r0.isDefault != r1.isDefault) {
   1953                     return query.get(0);
   1954                 }
   1955                 // If we have saved a preference for a preferred activity for
   1956                 // this Intent, use that.
   1957                 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
   1958                         flags, query, r0.priority);
   1959                 if (ri != null) {
   1960                     return ri;
   1961                 }
   1962                 return mResolveInfo;
   1963             }
   1964         }
   1965         return null;
   1966     }
   1967 
   1968     ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
   1969             int flags, List<ResolveInfo> query, int priority) {
   1970         synchronized (mPackages) {
   1971             if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
   1972             List<PreferredActivity> prefs =
   1973                     mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
   1974                             (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
   1975             if (prefs != null && prefs.size() > 0) {
   1976                 // First figure out how good the original match set is.
   1977                 // We will only allow preferred activities that came
   1978                 // from the same match quality.
   1979                 int match = 0;
   1980                 final int N = query.size();
   1981                 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
   1982                 for (int j=0; j<N; j++) {
   1983                     ResolveInfo ri = query.get(j);
   1984                     if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
   1985                             + ": 0x" + Integer.toHexString(match));
   1986                     if (ri.match > match) match = ri.match;
   1987                 }
   1988                 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
   1989                         + Integer.toHexString(match));
   1990                 match &= IntentFilter.MATCH_CATEGORY_MASK;
   1991                 final int M = prefs.size();
   1992                 for (int i=0; i<M; i++) {
   1993                     PreferredActivity pa = prefs.get(i);
   1994                     if (pa.mMatch != match) {
   1995                         continue;
   1996                     }
   1997                     ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
   1998                     if (DEBUG_PREFERRED) {
   1999                         Log.v(TAG, "Got preferred activity:");
   2000                         ai.dump(new LogPrinter(Log.INFO, TAG), "  ");
   2001                     }
   2002                     if (ai != null) {
   2003                         for (int j=0; j<N; j++) {
   2004                             ResolveInfo ri = query.get(j);
   2005                             if (!ri.activityInfo.applicationInfo.packageName
   2006                                     .equals(ai.applicationInfo.packageName)) {
   2007                                 continue;
   2008                             }
   2009                             if (!ri.activityInfo.name.equals(ai.name)) {
   2010                                 continue;
   2011                             }
   2012 
   2013                             // Okay we found a previously set preferred app.
   2014                             // If the result set is different from when this
   2015                             // was created, we need to clear it and re-ask the
   2016                             // user their preference.
   2017                             if (!pa.sameSet(query, priority)) {
   2018                                 Slog.i(TAG, "Result set changed, dropping preferred activity for "
   2019                                         + intent + " type " + resolvedType);
   2020                                 mSettings.mPreferredActivities.removeFilter(pa);
   2021                                 return null;
   2022                             }
   2023 
   2024                             // Yay!
   2025                             return ri;
   2026                         }
   2027                     }
   2028                 }
   2029             }
   2030         }
   2031         return null;
   2032     }
   2033 
   2034     public List<ResolveInfo> queryIntentActivities(Intent intent,
   2035             String resolvedType, int flags) {
   2036         ComponentName comp = intent.getComponent();
   2037         if (comp != null) {
   2038             List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
   2039             ActivityInfo ai = getActivityInfo(comp, flags);
   2040             if (ai != null) {
   2041                 ResolveInfo ri = new ResolveInfo();
   2042                 ri.activityInfo = ai;
   2043                 list.add(ri);
   2044             }
   2045             return list;
   2046         }
   2047 
   2048         synchronized (mPackages) {
   2049             String pkgName = intent.getPackage();
   2050             if (pkgName == null) {
   2051                 return (List<ResolveInfo>)mActivities.queryIntent(intent,
   2052                         resolvedType, flags);
   2053             }
   2054             PackageParser.Package pkg = mPackages.get(pkgName);
   2055             if (pkg != null) {
   2056                 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
   2057                         resolvedType, flags, pkg.activities);
   2058             }
   2059             return null;
   2060         }
   2061     }
   2062 
   2063     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
   2064             Intent[] specifics, String[] specificTypes, Intent intent,
   2065             String resolvedType, int flags) {
   2066         final String resultsAction = intent.getAction();
   2067 
   2068         List<ResolveInfo> results = queryIntentActivities(
   2069             intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
   2070         if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
   2071 
   2072         int specificsPos = 0;
   2073         int N;
   2074 
   2075         // todo: note that the algorithm used here is O(N^2).  This
   2076         // isn't a problem in our current environment, but if we start running
   2077         // into situations where we have more than 5 or 10 matches then this
   2078         // should probably be changed to something smarter...
   2079 
   2080         // First we go through and resolve each of the specific items
   2081         // that were supplied, taking care of removing any corresponding
   2082         // duplicate items in the generic resolve list.
   2083         if (specifics != null) {
   2084             for (int i=0; i<specifics.length; i++) {
   2085                 final Intent sintent = specifics[i];
   2086                 if (sintent == null) {
   2087                     continue;
   2088                 }
   2089 
   2090                 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
   2091                 String action = sintent.getAction();
   2092                 if (resultsAction != null && resultsAction.equals(action)) {
   2093                     // If this action was explicitly requested, then don't
   2094                     // remove things that have it.
   2095                     action = null;
   2096                 }
   2097                 ComponentName comp = sintent.getComponent();
   2098                 ResolveInfo ri = null;
   2099                 ActivityInfo ai = null;
   2100                 if (comp == null) {
   2101                     ri = resolveIntent(
   2102                         sintent,
   2103                         specificTypes != null ? specificTypes[i] : null,
   2104                         flags);
   2105                     if (ri == null) {
   2106                         continue;
   2107                     }
   2108                     if (ri == mResolveInfo) {
   2109                         // ACK!  Must do something better with this.
   2110                     }
   2111                     ai = ri.activityInfo;
   2112                     comp = new ComponentName(ai.applicationInfo.packageName,
   2113                             ai.name);
   2114                 } else {
   2115                     ai = getActivityInfo(comp, flags);
   2116                     if (ai == null) {
   2117                         continue;
   2118                     }
   2119                 }
   2120 
   2121                 // Look for any generic query activities that are duplicates
   2122                 // of this specific one, and remove them from the results.
   2123                 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
   2124                 N = results.size();
   2125                 int j;
   2126                 for (j=specificsPos; j<N; j++) {
   2127                     ResolveInfo sri = results.get(j);
   2128                     if ((sri.activityInfo.name.equals(comp.getClassName())
   2129                             && sri.activityInfo.applicationInfo.packageName.equals(
   2130                                     comp.getPackageName()))
   2131                         || (action != null && sri.filter.matchAction(action))) {
   2132                         results.remove(j);
   2133                         if (Config.LOGV) Log.v(
   2134                             TAG, "Removing duplicate item from " + j
   2135                             + " due to specific " + specificsPos);
   2136                         if (ri == null) {
   2137                             ri = sri;
   2138                         }
   2139                         j--;
   2140                         N--;
   2141                     }
   2142                 }
   2143 
   2144                 // Add this specific item to its proper place.
   2145                 if (ri == null) {
   2146                     ri = new ResolveInfo();
   2147                     ri.activityInfo = ai;
   2148                 }
   2149                 results.add(specificsPos, ri);
   2150                 ri.specificIndex = i;
   2151                 specificsPos++;
   2152             }
   2153         }
   2154 
   2155         // Now we go through the remaining generic results and remove any
   2156         // duplicate actions that are found here.
   2157         N = results.size();
   2158         for (int i=specificsPos; i<N-1; i++) {
   2159             final ResolveInfo rii = results.get(i);
   2160             if (rii.filter == null) {
   2161                 continue;
   2162             }
   2163 
   2164             // Iterate over all of the actions of this result's intent
   2165             // filter...  typically this should be just one.
   2166             final Iterator<String> it = rii.filter.actionsIterator();
   2167             if (it == null) {
   2168                 continue;
   2169             }
   2170             while (it.hasNext()) {
   2171                 final String action = it.next();
   2172                 if (resultsAction != null && resultsAction.equals(action)) {
   2173                     // If this action was explicitly requested, then don't
   2174                     // remove things that have it.
   2175                     continue;
   2176                 }
   2177                 for (int j=i+1; j<N; j++) {
   2178                     final ResolveInfo rij = results.get(j);
   2179                     if (rij.filter != null && rij.filter.hasAction(action)) {
   2180                         results.remove(j);
   2181                         if (Config.LOGV) Log.v(
   2182                             TAG, "Removing duplicate item from " + j
   2183                             + " due to action " + action + " at " + i);
   2184                         j--;
   2185                         N--;
   2186                     }
   2187                 }
   2188             }
   2189 
   2190             // If the caller didn't request filter information, drop it now
   2191             // so we don't have to marshall/unmarshall it.
   2192             if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
   2193                 rii.filter = null;
   2194             }
   2195         }
   2196 
   2197         // Filter out the caller activity if so requested.
   2198         if (caller != null) {
   2199             N = results.size();
   2200             for (int i=0; i<N; i++) {
   2201                 ActivityInfo ainfo = results.get(i).activityInfo;
   2202                 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
   2203                         && caller.getClassName().equals(ainfo.name)) {
   2204                     results.remove(i);
   2205                     break;
   2206                 }
   2207             }
   2208         }
   2209 
   2210         // If the caller didn't request filter information,
   2211         // drop them now so we don't have to
   2212         // marshall/unmarshall it.
   2213         if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
   2214             N = results.size();
   2215             for (int i=0; i<N; i++) {
   2216                 results.get(i).filter = null;
   2217             }
   2218         }
   2219 
   2220         if (Config.LOGV) Log.v(TAG, "Result: " + results);
   2221         return results;
   2222     }
   2223 
   2224     public List<ResolveInfo> queryIntentReceivers(Intent intent,
   2225             String resolvedType, int flags) {
   2226         ComponentName comp = intent.getComponent();
   2227         if (comp != null) {
   2228             List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
   2229             ActivityInfo ai = getReceiverInfo(comp, flags);
   2230             if (ai != null) {
   2231                 ResolveInfo ri = new ResolveInfo();
   2232                 ri.activityInfo = ai;
   2233                 list.add(ri);
   2234             }
   2235             return list;
   2236         }
   2237 
   2238         synchronized (mPackages) {
   2239             String pkgName = intent.getPackage();
   2240             if (pkgName == null) {
   2241                 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
   2242                         resolvedType, flags);
   2243             }
   2244             PackageParser.Package pkg = mPackages.get(pkgName);
   2245             if (pkg != null) {
   2246                 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
   2247                         resolvedType, flags, pkg.receivers);
   2248             }
   2249             return null;
   2250         }
   2251     }
   2252 
   2253     public ResolveInfo resolveService(Intent intent, String resolvedType,
   2254             int flags) {
   2255         List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
   2256                 flags);
   2257         if (query != null) {
   2258             if (query.size() >= 1) {
   2259                 // If there is more than one service with the same priority,
   2260                 // just arbitrarily pick the first one.
   2261                 return query.get(0);
   2262             }
   2263         }
   2264         return null;
   2265     }
   2266 
   2267     public List<ResolveInfo> queryIntentServices(Intent intent,
   2268             String resolvedType, int flags) {
   2269         ComponentName comp = intent.getComponent();
   2270         if (comp != null) {
   2271             List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
   2272             ServiceInfo si = getServiceInfo(comp, flags);
   2273             if (si != null) {
   2274                 ResolveInfo ri = new ResolveInfo();
   2275                 ri.serviceInfo = si;
   2276                 list.add(ri);
   2277             }
   2278             return list;
   2279         }
   2280 
   2281         synchronized (mPackages) {
   2282             String pkgName = intent.getPackage();
   2283             if (pkgName == null) {
   2284                 return (List<ResolveInfo>)mServices.queryIntent(intent,
   2285                         resolvedType, flags);
   2286             }
   2287             PackageParser.Package pkg = mPackages.get(pkgName);
   2288             if (pkg != null) {
   2289                 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
   2290                         resolvedType, flags, pkg.services);
   2291             }
   2292             return null;
   2293         }
   2294     }
   2295 
   2296     public List<PackageInfo> getInstalledPackages(int flags) {
   2297         ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
   2298 
   2299         synchronized (mPackages) {
   2300             if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
   2301                 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
   2302                 while (i.hasNext()) {
   2303                     final PackageSetting ps = i.next();
   2304                     PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
   2305                     if(psPkg != null) {
   2306                         finalList.add(psPkg);
   2307                     }
   2308                 }
   2309             }
   2310             else {
   2311                 Iterator<PackageParser.Package> i = mPackages.values().iterator();
   2312                 while (i.hasNext()) {
   2313                     final PackageParser.Package p = i.next();
   2314                     if (p.applicationInfo != null) {
   2315                         PackageInfo pi = generatePackageInfo(p, flags);
   2316                         if(pi != null) {
   2317                             finalList.add(pi);
   2318                         }
   2319                     }
   2320                 }
   2321             }
   2322         }
   2323         return finalList;
   2324     }
   2325 
   2326     public List<ApplicationInfo> getInstalledApplications(int flags) {
   2327         ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
   2328         synchronized(mPackages) {
   2329             if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
   2330                 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
   2331                 while (i.hasNext()) {
   2332                     final PackageSetting ps = i.next();
   2333                     ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
   2334                     if(ai != null) {
   2335                         finalList.add(ai);
   2336                     }
   2337                 }
   2338             }
   2339             else {
   2340                 Iterator<PackageParser.Package> i = mPackages.values().iterator();
   2341                 while (i.hasNext()) {
   2342                     final PackageParser.Package p = i.next();
   2343                     if (p.applicationInfo != null) {
   2344                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
   2345                         if(ai != null) {
   2346                             finalList.add(ai);
   2347                         }
   2348                     }
   2349                 }
   2350             }
   2351         }
   2352         return finalList;
   2353     }
   2354 
   2355     public List<ApplicationInfo> getPersistentApplications(int flags) {
   2356         ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
   2357 
   2358         synchronized (mPackages) {
   2359             Iterator<PackageParser.Package> i = mPackages.values().iterator();
   2360             while (i.hasNext()) {
   2361                 PackageParser.Package p = i.next();
   2362                 if (p.applicationInfo != null
   2363                         && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
   2364                         && (!mSafeMode || (p.applicationInfo.flags
   2365                                 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
   2366                     finalList.add(p.applicationInfo);
   2367                 }
   2368             }
   2369         }
   2370 
   2371         return finalList;
   2372     }
   2373 
   2374     public ProviderInfo resolveContentProvider(String name, int flags) {
   2375         synchronized (mPackages) {
   2376             final PackageParser.Provider provider = mProviders.get(name);
   2377             return provider != null
   2378                     && mSettings.isEnabledLP(provider.info, flags)
   2379                     && (!mSafeMode || (provider.info.applicationInfo.flags
   2380                             &ApplicationInfo.FLAG_SYSTEM) != 0)
   2381                     ? PackageParser.generateProviderInfo(provider, flags)
   2382                     : null;
   2383         }
   2384     }
   2385 
   2386     /**
   2387      * @deprecated
   2388      */
   2389     public void querySyncProviders(List outNames, List outInfo) {
   2390         synchronized (mPackages) {
   2391             Iterator<Map.Entry<String, PackageParser.Provider>> i
   2392                 = mProviders.entrySet().iterator();
   2393 
   2394             while (i.hasNext()) {
   2395                 Map.Entry<String, PackageParser.Provider> entry = i.next();
   2396                 PackageParser.Provider p = entry.getValue();
   2397 
   2398                 if (p.syncable
   2399                         && (!mSafeMode || (p.info.applicationInfo.flags
   2400                                 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
   2401                     outNames.add(entry.getKey());
   2402                     outInfo.add(PackageParser.generateProviderInfo(p, 0));
   2403                 }
   2404             }
   2405         }
   2406     }
   2407 
   2408     public List<ProviderInfo> queryContentProviders(String processName,
   2409             int uid, int flags) {
   2410         ArrayList<ProviderInfo> finalList = null;
   2411 
   2412         synchronized (mPackages) {
   2413             Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
   2414             while (i.hasNext()) {
   2415                 PackageParser.Provider p = i.next();
   2416                 if (p.info.authority != null
   2417                     && (processName == null ||
   2418                             (p.info.processName.equals(processName)
   2419                                     && p.info.applicationInfo.uid == uid))
   2420                     && mSettings.isEnabledLP(p.info, flags)
   2421                     && (!mSafeMode || (p.info.applicationInfo.flags
   2422                             &ApplicationInfo.FLAG_SYSTEM) != 0)) {
   2423                     if (finalList == null) {
   2424                         finalList = new ArrayList<ProviderInfo>(3);
   2425                     }
   2426                     finalList.add(PackageParser.generateProviderInfo(p,
   2427                             flags));
   2428                 }
   2429             }
   2430         }
   2431 
   2432         if (finalList != null) {
   2433             Collections.sort(finalList, mProviderInitOrderSorter);
   2434         }
   2435 
   2436         return finalList;
   2437     }
   2438 
   2439     public InstrumentationInfo getInstrumentationInfo(ComponentName name,
   2440             int flags) {
   2441         synchronized (mPackages) {
   2442             final PackageParser.Instrumentation i = mInstrumentation.get(name);
   2443             return PackageParser.generateInstrumentationInfo(i, flags);
   2444         }
   2445     }
   2446 
   2447     public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
   2448             int flags) {
   2449         ArrayList<InstrumentationInfo> finalList =
   2450             new ArrayList<InstrumentationInfo>();
   2451 
   2452         synchronized (mPackages) {
   2453             Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
   2454             while (i.hasNext()) {
   2455                 PackageParser.Instrumentation p = i.next();
   2456                 if (targetPackage == null
   2457                         || targetPackage.equals(p.info.targetPackage)) {
   2458                     finalList.add(PackageParser.generateInstrumentationInfo(p,
   2459                             flags));
   2460                 }
   2461             }
   2462         }
   2463 
   2464         return finalList;
   2465     }
   2466 
   2467     private void scanDirLI(File dir, int flags, int scanMode) {
   2468         Log.d(TAG, "Scanning app dir " + dir);
   2469 
   2470         String[] files = dir.list();
   2471 
   2472         int i;
   2473         for (i=0; i<files.length; i++) {
   2474             File file = new File(dir, files[i]);
   2475             if (!isPackageFilename(files[i])) {
   2476                 // Ignore entries which are not apk's
   2477                 continue;
   2478             }
   2479             PackageParser.Package pkg = scanPackageLI(file,
   2480                     flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
   2481             // Don't mess around with apps in system partition.
   2482             if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
   2483                     mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
   2484                 // Delete the apk
   2485                 Slog.w(TAG, "Cleaning up failed install of " + file);
   2486                 file.delete();
   2487             }
   2488         }
   2489     }
   2490 
   2491     private static File getSettingsProblemFile() {
   2492         File dataDir = Environment.getDataDirectory();
   2493         File systemDir = new File(dataDir, "system");
   2494         File fname = new File(systemDir, "uiderrors.txt");
   2495         return fname;
   2496     }
   2497 
   2498     private static void reportSettingsProblem(int priority, String msg) {
   2499         try {
   2500             File fname = getSettingsProblemFile();
   2501             FileOutputStream out = new FileOutputStream(fname, true);
   2502             PrintWriter pw = new PrintWriter(out);
   2503             SimpleDateFormat formatter = new SimpleDateFormat();
   2504             String dateString = formatter.format(new Date(System.currentTimeMillis()));
   2505             pw.println(dateString + ": " + msg);
   2506             pw.close();
   2507             FileUtils.setPermissions(
   2508                     fname.toString(),
   2509                     FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
   2510                     -1, -1);
   2511         } catch (java.io.IOException e) {
   2512         }
   2513         Slog.println(priority, TAG, msg);
   2514     }
   2515 
   2516     private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
   2517             PackageParser.Package pkg, File srcFile, int parseFlags) {
   2518         if (GET_CERTIFICATES) {
   2519             if (ps != null
   2520                     && ps.codePath.equals(srcFile)
   2521                     && ps.getTimeStamp() == srcFile.lastModified()) {
   2522                 if (ps.signatures.mSignatures != null
   2523                         && ps.signatures.mSignatures.length != 0) {
   2524                     // Optimization: reuse the existing cached certificates
   2525                     // if the package appears to be unchanged.
   2526                     pkg.mSignatures = ps.signatures.mSignatures;
   2527                     return true;
   2528                 }
   2529 
   2530                 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures.  Collecting certs again to recover them.");
   2531             } else {
   2532                 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
   2533             }
   2534 
   2535             if (!pp.collectCertificates(pkg, parseFlags)) {
   2536                 mLastScanError = pp.getParseError();
   2537                 return false;
   2538             }
   2539         }
   2540         return true;
   2541     }
   2542 
   2543     /*
   2544      *  Scan a package and return the newly parsed package.
   2545      *  Returns null in case of errors and the error code is stored in mLastScanError
   2546      */
   2547     private PackageParser.Package scanPackageLI(File scanFile,
   2548             int parseFlags, int scanMode) {
   2549         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
   2550         String scanPath = scanFile.getPath();
   2551         parseFlags |= mDefParseFlags;
   2552         PackageParser pp = new PackageParser(scanPath);
   2553         pp.setSeparateProcesses(mSeparateProcesses);
   2554         final PackageParser.Package pkg = pp.parsePackage(scanFile,
   2555                 scanPath, mMetrics, parseFlags);
   2556         if (pkg == null) {
   2557             mLastScanError = pp.getParseError();
   2558             return null;
   2559         }
   2560         PackageSetting ps = null;
   2561         PackageSetting updatedPkg;
   2562         synchronized (mPackages) {
   2563             // Look to see if we already know about this package.
   2564             String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
   2565             if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
   2566                 // This package has been renamed to its original name.  Let's
   2567                 // use that.
   2568                 ps = mSettings.peekPackageLP(oldName);
   2569             }
   2570             // If there was no original package, see one for the real package name.
   2571             if (ps == null) {
   2572                 ps = mSettings.peekPackageLP(pkg.packageName);
   2573             }
   2574             // Check to see if this package could be hiding/updating a system
   2575             // package.  Must look for it either under the original or real
   2576             // package name depending on our state.
   2577             updatedPkg = mSettings.mDisabledSysPackages.get(
   2578                     ps != null ? ps.name : pkg.packageName);
   2579         }
   2580         // First check if this is a system package that may involve an update
   2581         if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
   2582             if (!ps.codePath.equals(scanFile)) {
   2583                 // The path has changed from what was last scanned...  check the
   2584                 // version of the new path against what we have stored to determine
   2585                 // what to do.
   2586                 if (pkg.mVersionCode < ps.versionCode) {
   2587                     // The system package has been updated and the code path does not match
   2588                     // Ignore entry. Skip it.
   2589                     Log.i(TAG, "Package " + ps.name + " at " + scanFile
   2590                             + "ignored: updated version " + ps.versionCode
   2591                             + " better than this " + pkg.mVersionCode);
   2592                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
   2593                     return null;
   2594                 } else {
   2595                     // The current app on the system partion is better than
   2596                     // what we have updated to on the data partition; switch
   2597                     // back to the system partition version.
   2598                     // At this point, its safely assumed that package installation for
   2599                     // apps in system partition will go through. If not there won't be a working
   2600                     // version of the app
   2601                     synchronized (mPackages) {
   2602                         // Just remove the loaded entries from package lists.
   2603                         mPackages.remove(ps.name);
   2604                     }
   2605                     Slog.w(TAG, "Package " + ps.name + " at " + scanFile
   2606                             + "reverting from " + ps.codePathString
   2607                             + ": new version " + pkg.mVersionCode
   2608                             + " better than installed " + ps.versionCode);
   2609                     InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
   2610                     args.cleanUpResourcesLI();
   2611                     removeNativeBinariesLI(pkg);
   2612                     mSettings.enableSystemPackageLP(ps.name);
   2613                 }
   2614             }
   2615         }
   2616         if (updatedPkg != null) {
   2617             // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
   2618             parseFlags |= PackageParser.PARSE_IS_SYSTEM;
   2619         }
   2620         // Verify certificates against what was last scanned
   2621         if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
   2622             Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
   2623             return null;
   2624         }
   2625         // The apk is forward locked (not public) if its code and resources
   2626         // are kept in different files.
   2627         // TODO grab this value from PackageSettings
   2628         if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
   2629             parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
   2630         }
   2631 
   2632         String codePath = null;
   2633         String resPath = null;
   2634         if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
   2635             if (ps != null && ps.resourcePathString != null) {
   2636                 resPath = ps.resourcePathString;
   2637             } else {
   2638                 // Should not happen at all. Just log an error.
   2639                 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
   2640             }
   2641         } else {
   2642             resPath = pkg.mScanPath;
   2643         }
   2644         codePath = pkg.mScanPath;
   2645         // Set application objects path explicitly.
   2646         setApplicationInfoPaths(pkg, codePath, resPath);
   2647         // Note that we invoke the following method only if we are about to unpack an application
   2648         return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
   2649     }
   2650 
   2651     private static void setApplicationInfoPaths(PackageParser.Package pkg,
   2652             String destCodePath, String destResPath) {
   2653         pkg.mPath = pkg.mScanPath = destCodePath;
   2654         pkg.applicationInfo.sourceDir = destCodePath;
   2655         pkg.applicationInfo.publicSourceDir = destResPath;
   2656     }
   2657 
   2658     private static String fixProcessName(String defProcessName,
   2659             String processName, int uid) {
   2660         if (processName == null) {
   2661             return defProcessName;
   2662         }
   2663         return processName;
   2664     }
   2665 
   2666     private boolean verifySignaturesLP(PackageSetting pkgSetting,
   2667             PackageParser.Package pkg) {
   2668         if (pkgSetting.signatures.mSignatures != null) {
   2669             // Already existing package. Make sure signatures match
   2670             if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
   2671                 PackageManager.SIGNATURE_MATCH) {
   2672                     Slog.e(TAG, "Package " + pkg.packageName
   2673                             + " signatures do not match the previously installed version; ignoring!");
   2674                     mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
   2675                     return false;
   2676                 }
   2677         }
   2678         // Check for shared user signatures
   2679         if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
   2680             if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
   2681                     pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
   2682                 Slog.e(TAG, "Package " + pkg.packageName
   2683                         + " has no signatures that match those in shared user "
   2684                         + pkgSetting.sharedUser.name + "; ignoring!");
   2685                 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
   2686                 return false;
   2687             }
   2688         }
   2689         return true;
   2690     }
   2691 
   2692     public boolean performDexOpt(String packageName) {
   2693         if (!mNoDexOpt) {
   2694             return false;
   2695         }
   2696 
   2697         PackageParser.Package p;
   2698         synchronized (mPackages) {
   2699             p = mPackages.get(packageName);
   2700             if (p == null || p.mDidDexOpt) {
   2701                 return false;
   2702             }
   2703         }
   2704         synchronized (mInstallLock) {
   2705             return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
   2706         }
   2707     }
   2708 
   2709     static final int DEX_OPT_SKIPPED = 0;
   2710     static final int DEX_OPT_PERFORMED = 1;
   2711     static final int DEX_OPT_FAILED = -1;
   2712 
   2713     private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
   2714         boolean performed = false;
   2715         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
   2716             String path = pkg.mScanPath;
   2717             int ret = 0;
   2718             try {
   2719                 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
   2720                     ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
   2721                             !isForwardLocked(pkg));
   2722                     pkg.mDidDexOpt = true;
   2723                     performed = true;
   2724                 }
   2725             } catch (FileNotFoundException e) {
   2726                 Slog.w(TAG, "Apk not found for dexopt: " + path);
   2727                 ret = -1;
   2728             } catch (IOException e) {
   2729                 Slog.w(TAG, "IOException reading apk: " + path, e);
   2730                 ret = -1;
   2731             } catch (dalvik.system.StaleDexCacheError e) {
   2732                 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
   2733                 ret = -1;
   2734             } catch (Exception e) {
   2735                 Slog.w(TAG, "Exception when doing dexopt : ", e);
   2736                 ret = -1;
   2737             }
   2738             if (ret < 0) {
   2739                 //error from installer
   2740                 return DEX_OPT_FAILED;
   2741             }
   2742         }
   2743 
   2744         return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
   2745     }
   2746 
   2747     private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
   2748         if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
   2749             Slog.w(TAG, "Unable to update from " + oldPkg.name
   2750                     + " to " + newPkg.packageName
   2751                     + ": old package not in system partition");
   2752             return false;
   2753         } else if (mPackages.get(oldPkg.name) != null) {
   2754             Slog.w(TAG, "Unable to update from " + oldPkg.name
   2755                     + " to " + newPkg.packageName
   2756                     + ": old package still exists");
   2757             return false;
   2758         }
   2759         return true;
   2760     }
   2761 
   2762     private File getDataPathForPackage(PackageParser.Package pkg) {
   2763         return new File(mAppDataDir, pkg.packageName);
   2764     }
   2765 
   2766     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
   2767             int parseFlags, int scanMode) {
   2768         File scanFile = new File(pkg.mScanPath);
   2769         if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
   2770                 pkg.applicationInfo.publicSourceDir == null) {
   2771             // Bail out. The resource and code paths haven't been set.
   2772             Slog.w(TAG, " Code and resource paths haven't been set correctly");
   2773             mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
   2774             return null;
   2775         }
   2776         mScanningPath = scanFile;
   2777         if (pkg == null) {
   2778             mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
   2779             return null;
   2780         }
   2781 
   2782         if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
   2783             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
   2784         }
   2785 
   2786         if (pkg.packageName.equals("android")) {
   2787             synchronized (mPackages) {
   2788                 if (mAndroidApplication != null) {
   2789                     Slog.w(TAG, "*************************************************");
   2790                     Slog.w(TAG, "Core android package being redefined.  Skipping.");
   2791                     Slog.w(TAG, " file=" + mScanningPath);
   2792                     Slog.w(TAG, "*************************************************");
   2793                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
   2794                     return null;
   2795                 }
   2796 
   2797                 // Set up information for our fall-back user intent resolution
   2798                 // activity.
   2799                 mPlatformPackage = pkg;
   2800                 pkg.mVersionCode = mSdkVersion;
   2801                 mAndroidApplication = pkg.applicationInfo;
   2802                 mResolveActivity.applicationInfo = mAndroidApplication;
   2803                 mResolveActivity.name = ResolverActivity.class.getName();
   2804                 mResolveActivity.packageName = mAndroidApplication.packageName;
   2805                 mResolveActivity.processName = mAndroidApplication.processName;
   2806                 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
   2807                 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
   2808                 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
   2809                 mResolveActivity.exported = true;
   2810                 mResolveActivity.enabled = true;
   2811                 mResolveInfo.activityInfo = mResolveActivity;
   2812                 mResolveInfo.priority = 0;
   2813                 mResolveInfo.preferredOrder = 0;
   2814                 mResolveInfo.match = 0;
   2815                 mResolveComponentName = new ComponentName(
   2816                         mAndroidApplication.packageName, mResolveActivity.name);
   2817             }
   2818         }
   2819 
   2820         if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
   2821                 TAG, "Scanning package " + pkg.packageName);
   2822         if (mPackages.containsKey(pkg.packageName)
   2823                 || mSharedLibraries.containsKey(pkg.packageName)) {
   2824             Slog.w(TAG, "*************************************************");
   2825             Slog.w(TAG, "Application package " + pkg.packageName
   2826                     + " already installed.  Skipping duplicate.");
   2827             Slog.w(TAG, "*************************************************");
   2828             mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
   2829             return null;
   2830         }
   2831 
   2832         // Initialize package source and resource directories
   2833         File destCodeFile = new File(pkg.applicationInfo.sourceDir);
   2834         File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
   2835 
   2836         SharedUserSetting suid = null;
   2837         PackageSetting pkgSetting = null;
   2838 
   2839         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
   2840             // Only system apps can use these features.
   2841             pkg.mOriginalPackages = null;
   2842             pkg.mRealPackage = null;
   2843             pkg.mAdoptPermissions = null;
   2844         }
   2845 
   2846         synchronized (mPackages) {
   2847             // Check all shared libraries and map to their actual file path.
   2848             if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
   2849                 if (mTmpSharedLibraries == null ||
   2850                         mTmpSharedLibraries.length < mSharedLibraries.size()) {
   2851                     mTmpSharedLibraries = new String[mSharedLibraries.size()];
   2852                 }
   2853                 int num = 0;
   2854                 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
   2855                 for (int i=0; i<N; i++) {
   2856                     String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
   2857                     if (file == null) {
   2858                         Slog.e(TAG, "Package " + pkg.packageName
   2859                                 + " requires unavailable shared library "
   2860                                 + pkg.usesLibraries.get(i) + "; failing!");
   2861                         mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
   2862                         return null;
   2863                     }
   2864                     mTmpSharedLibraries[num] = file;
   2865                     num++;
   2866                 }
   2867                 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
   2868                 for (int i=0; i<N; i++) {
   2869                     String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
   2870                     if (file == null) {
   2871                         Slog.w(TAG, "Package " + pkg.packageName
   2872                                 + " desires unavailable shared library "
   2873                                 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
   2874                     } else {
   2875                         mTmpSharedLibraries[num] = file;
   2876                         num++;
   2877                     }
   2878                 }
   2879                 if (num > 0) {
   2880                     pkg.usesLibraryFiles = new String[num];
   2881                     System.arraycopy(mTmpSharedLibraries, 0,
   2882                             pkg.usesLibraryFiles, 0, num);
   2883                 }
   2884 
   2885                 if (pkg.reqFeatures != null) {
   2886                     N = pkg.reqFeatures.size();
   2887                     for (int i=0; i<N; i++) {
   2888                         FeatureInfo fi = pkg.reqFeatures.get(i);
   2889                         if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
   2890                             // Don't care.
   2891                             continue;
   2892                         }
   2893 
   2894                         if (fi.name != null) {
   2895                             if (mAvailableFeatures.get(fi.name) == null) {
   2896                                 Slog.e(TAG, "Package " + pkg.packageName
   2897                                         + " requires unavailable feature "
   2898                                         + fi.name + "; failing!");
   2899                                 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
   2900                                 return null;
   2901                             }
   2902                         }
   2903                     }
   2904                 }
   2905             }
   2906 
   2907             if (pkg.mSharedUserId != null) {
   2908                 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
   2909                         pkg.applicationInfo.flags, true);
   2910                 if (suid == null) {
   2911                     Slog.w(TAG, "Creating application package " + pkg.packageName
   2912                             + " for shared user failed");
   2913                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   2914                     return null;
   2915                 }
   2916                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
   2917                     Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
   2918                             + suid.userId + "): packages=" + suid.packages);
   2919                 }
   2920             }
   2921 
   2922             if (false) {
   2923                 if (pkg.mOriginalPackages != null) {
   2924                     Log.w(TAG, "WAITING FOR DEBUGGER");
   2925                     Debug.waitForDebugger();
   2926                     Log.i(TAG, "Package " + pkg.packageName + " from original packages"
   2927                             + pkg.mOriginalPackages);
   2928                 }
   2929             }
   2930 
   2931             // Check if we are renaming from an original package name.
   2932             PackageSetting origPackage = null;
   2933             String realName = null;
   2934             if (pkg.mOriginalPackages != null) {
   2935                 // This package may need to be renamed to a previously
   2936                 // installed name.  Let's check on that...
   2937                 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
   2938                 if (pkg.mOriginalPackages.contains(renamed)) {
   2939                     // This package had originally been installed as the
   2940                     // original name, and we have already taken care of
   2941                     // transitioning to the new one.  Just update the new
   2942                     // one to continue using the old name.
   2943                     realName = pkg.mRealPackage;
   2944                     if (!pkg.packageName.equals(renamed)) {
   2945                         // Callers into this function may have already taken
   2946                         // care of renaming the package; only do it here if
   2947                         // it is not already done.
   2948                         pkg.setPackageName(renamed);
   2949                     }
   2950 
   2951                 } else {
   2952                     for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
   2953                         if ((origPackage=mSettings.peekPackageLP(
   2954                                 pkg.mOriginalPackages.get(i))) != null) {
   2955                             // We do have the package already installed under its
   2956                             // original name...  should we use it?
   2957                             if (!verifyPackageUpdate(origPackage, pkg)) {
   2958                                 // New package is not compatible with original.
   2959                                 origPackage = null;
   2960                                 continue;
   2961                             } else if (origPackage.sharedUser != null) {
   2962                                 // Make sure uid is compatible between packages.
   2963                                 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
   2964                                     Slog.w(TAG, "Unable to migrate data from " + origPackage.name
   2965                                             + " to " + pkg.packageName + ": old uid "
   2966                                             + origPackage.sharedUser.name
   2967                                             + " differs from " + pkg.mSharedUserId);
   2968                                     origPackage = null;
   2969                                     continue;
   2970                                 }
   2971                             } else {
   2972                                 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
   2973                                         + pkg.packageName + " to old name " + origPackage.name);
   2974                             }
   2975                             break;
   2976                         }
   2977                     }
   2978                 }
   2979             }
   2980 
   2981             if (mTransferedPackages.contains(pkg.packageName)) {
   2982                 Slog.w(TAG, "Package " + pkg.packageName
   2983                         + " was transferred to another, but its .apk remains");
   2984             }
   2985 
   2986             // Just create the setting, don't add it yet. For already existing packages
   2987             // the PkgSetting exists already and doesn't have to be created.
   2988             pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
   2989                             destResourceFile, pkg.applicationInfo.flags, true, false);
   2990             if (pkgSetting == null) {
   2991                 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
   2992                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   2993                 return null;
   2994             }
   2995 
   2996             if (pkgSetting.origPackage != null) {
   2997                 // If we are first transitioning from an original package,
   2998                 // fix up the new package's name now.  We need to do this after
   2999                 // looking up the package under its new name, so getPackageLP
   3000                 // can take care of fiddling things correctly.
   3001                 pkg.setPackageName(origPackage.name);
   3002 
   3003                 // File a report about this.
   3004                 String msg = "New package " + pkgSetting.realName
   3005                         + " renamed to replace old package " + pkgSetting.name;
   3006                 reportSettingsProblem(Log.WARN, msg);
   3007 
   3008                 // Make a note of it.
   3009                 mTransferedPackages.add(origPackage.name);
   3010 
   3011                 // No longer need to retain this.
   3012                 pkgSetting.origPackage = null;
   3013             }
   3014 
   3015             if (realName != null) {
   3016                 // Make a note of it.
   3017                 mTransferedPackages.add(pkg.packageName);
   3018             }
   3019 
   3020             if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
   3021                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
   3022             }
   3023 
   3024             pkg.applicationInfo.uid = pkgSetting.userId;
   3025             pkg.mExtras = pkgSetting;
   3026 
   3027             if (!verifySignaturesLP(pkgSetting, pkg)) {
   3028                 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
   3029                     return null;
   3030                 }
   3031                 // The signature has changed, but this package is in the system
   3032                 // image...  let's recover!
   3033                 pkgSetting.signatures.mSignatures = pkg.mSignatures;
   3034                 // However...  if this package is part of a shared user, but it
   3035                 // doesn't match the signature of the shared user, let's fail.
   3036                 // What this means is that you can't change the signatures
   3037                 // associated with an overall shared user, which doesn't seem all
   3038                 // that unreasonable.
   3039                 if (pkgSetting.sharedUser != null) {
   3040                     if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
   3041                             pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
   3042                         Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
   3043                         mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
   3044                         return null;
   3045                     }
   3046                 }
   3047                 // File a report about this.
   3048                 String msg = "System package " + pkg.packageName
   3049                         + " signature changed; retaining data.";
   3050                 reportSettingsProblem(Log.WARN, msg);
   3051             }
   3052 
   3053             // Verify that this new package doesn't have any content providers
   3054             // that conflict with existing packages.  Only do this if the
   3055             // package isn't already installed, since we don't want to break
   3056             // things that are installed.
   3057             if ((scanMode&SCAN_NEW_INSTALL) != 0) {
   3058                 int N = pkg.providers.size();
   3059                 int i;
   3060                 for (i=0; i<N; i++) {
   3061                     PackageParser.Provider p = pkg.providers.get(i);
   3062                     if (p.info.authority != null) {
   3063                         String names[] = p.info.authority.split(";");
   3064                         for (int j = 0; j < names.length; j++) {
   3065                             if (mProviders.containsKey(names[j])) {
   3066                                 PackageParser.Provider other = mProviders.get(names[j]);
   3067                                 Slog.w(TAG, "Can't install because provider name " + names[j] +
   3068                                         " (in package " + pkg.applicationInfo.packageName +
   3069                                         ") is already used by "
   3070                                         + ((other != null && other.getComponentName() != null)
   3071                                                 ? other.getComponentName().getPackageName() : "?"));
   3072                                 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
   3073                                 return null;
   3074                             }
   3075                         }
   3076                     }
   3077                 }
   3078             }
   3079         }
   3080 
   3081         final String pkgName = pkg.packageName;
   3082 
   3083         if (pkg.mAdoptPermissions != null) {
   3084             // This package wants to adopt ownership of permissions from
   3085             // another package.
   3086             for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
   3087                 String origName = pkg.mAdoptPermissions.get(i);
   3088                 PackageSetting orig = mSettings.peekPackageLP(origName);
   3089                 if (orig != null) {
   3090                     if (verifyPackageUpdate(orig, pkg)) {
   3091                         Slog.i(TAG, "Adopting permissions from "
   3092                                 + origName + " to " + pkg.packageName);
   3093                         mSettings.transferPermissions(origName, pkg.packageName);
   3094                     }
   3095                 }
   3096             }
   3097         }
   3098 
   3099         long scanFileTime = scanFile.lastModified();
   3100         final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
   3101         final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
   3102         pkg.applicationInfo.processName = fixProcessName(
   3103                 pkg.applicationInfo.packageName,
   3104                 pkg.applicationInfo.processName,
   3105                 pkg.applicationInfo.uid);
   3106 
   3107         File dataPath;
   3108         if (mPlatformPackage == pkg) {
   3109             // The system package is special.
   3110             dataPath = new File (Environment.getDataDirectory(), "system");
   3111             pkg.applicationInfo.dataDir = dataPath.getPath();
   3112         } else {
   3113             // This is a normal package, need to make its data directory.
   3114             dataPath = getDataPathForPackage(pkg);
   3115 
   3116             boolean uidError = false;
   3117 
   3118             if (dataPath.exists()) {
   3119                 mOutPermissions[1] = 0;
   3120                 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
   3121                 if (mOutPermissions[1] == pkg.applicationInfo.uid
   3122                         || !Process.supportsProcesses()) {
   3123                     pkg.applicationInfo.dataDir = dataPath.getPath();
   3124                 } else {
   3125                     boolean recovered = false;
   3126                     if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
   3127                         // If this is a system app, we can at least delete its
   3128                         // current data so the application will still work.
   3129                         if (mInstaller != null) {
   3130                             int ret = mInstaller.remove(pkgName);
   3131                             if (ret >= 0) {
   3132                                 // Old data gone!
   3133                                 String msg = "System package " + pkg.packageName
   3134                                         + " has changed from uid: "
   3135                                         + mOutPermissions[1] + " to "
   3136                                         + pkg.applicationInfo.uid + "; old data erased";
   3137                                 reportSettingsProblem(Log.WARN, msg);
   3138                                 recovered = true;
   3139 
   3140                                 // And now re-install the app.
   3141                                 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
   3142                                         pkg.applicationInfo.uid);
   3143                                 if (ret == -1) {
   3144                                     // Ack should not happen!
   3145                                     msg = "System package " + pkg.packageName
   3146                                             + " could not have data directory re-created after delete.";
   3147                                     reportSettingsProblem(Log.WARN, msg);
   3148                                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   3149                                     return null;
   3150                                 }
   3151                             }
   3152                         }
   3153                         if (!recovered) {
   3154                             mHasSystemUidErrors = true;
   3155                         }
   3156                     }
   3157                     if (!recovered) {
   3158                         pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
   3159                             + pkg.applicationInfo.uid + "/fs_"
   3160                             + mOutPermissions[1];
   3161                         String msg = "Package " + pkg.packageName
   3162                                 + " has mismatched uid: "
   3163                                 + mOutPermissions[1] + " on disk, "
   3164                                 + pkg.applicationInfo.uid + " in settings";
   3165                         synchronized (mPackages) {
   3166                             mSettings.mReadMessages.append(msg);
   3167                             mSettings.mReadMessages.append('\n');
   3168                             uidError = true;
   3169                             if (!pkgSetting.uidError) {
   3170                                 reportSettingsProblem(Log.ERROR, msg);
   3171                             }
   3172                         }
   3173                     }
   3174                 }
   3175                 pkg.applicationInfo.dataDir = dataPath.getPath();
   3176             } else {
   3177                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
   3178                     Log.v(TAG, "Want this data dir: " + dataPath);
   3179                 //invoke installer to do the actual installation
   3180                 if (mInstaller != null) {
   3181                     int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
   3182                             pkg.applicationInfo.uid);
   3183                     if(ret < 0) {
   3184                         // Error from installer
   3185                         mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   3186                         return null;
   3187                     }
   3188                 } else {
   3189                     dataPath.mkdirs();
   3190                     if (dataPath.exists()) {
   3191                         FileUtils.setPermissions(
   3192                             dataPath.toString(),
   3193                             FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
   3194                             pkg.applicationInfo.uid, pkg.applicationInfo.uid);
   3195                     }
   3196                 }
   3197                 if (dataPath.exists()) {
   3198                     pkg.applicationInfo.dataDir = dataPath.getPath();
   3199                 } else {
   3200                     Slog.w(TAG, "Unable to create data directory: " + dataPath);
   3201                     pkg.applicationInfo.dataDir = null;
   3202                 }
   3203             }
   3204 
   3205             pkgSetting.uidError = uidError;
   3206         }
   3207 
   3208         // Perform shared library installation and dex validation and
   3209         // optimization, if this is not a system app.
   3210         if (mInstaller != null) {
   3211             String path = scanFile.getPath();
   3212             if (scanFileNewer) {
   3213                 // Note: We don't want to unpack the native binaries for
   3214                 //       system applications, unless they have been updated
   3215                 //       (the binaries are already under /system/lib).
   3216                 //
   3217                 //       In other words, we're going to unpack the binaries
   3218                 //       only for non-system apps and system app upgrades.
   3219                 //
   3220                 int flags = pkg.applicationInfo.flags;
   3221                 if ((flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
   3222                     (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
   3223                     Log.i(TAG, path + " changed; unpacking");
   3224                     int err = cachePackageSharedLibsLI(pkg, scanFile);
   3225                     if (err != PackageManager.INSTALL_SUCCEEDED) {
   3226                         mLastScanError = err;
   3227                         return null;
   3228                     }
   3229                 }
   3230             }
   3231             pkg.mScanPath = path;
   3232 
   3233             if ((scanMode&SCAN_NO_DEX) == 0) {
   3234                 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
   3235                     mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
   3236                     return null;
   3237                 }
   3238             }
   3239         }
   3240 
   3241         if (mFactoryTest && pkg.requestedPermissions.contains(
   3242                 android.Manifest.permission.FACTORY_TEST)) {
   3243             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
   3244         }
   3245 
   3246         // Request the ActivityManager to kill the process(only for existing packages)
   3247         // so that we do not end up in a confused state while the user is still using the older
   3248         // version of the application while the new one gets installed.
   3249         if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
   3250             killApplication(pkg.applicationInfo.packageName,
   3251                         pkg.applicationInfo.uid);
   3252         }
   3253 
   3254         synchronized (mPackages) {
   3255             // We don't expect installation to fail beyond this point,
   3256             if ((scanMode&SCAN_MONITOR) != 0) {
   3257                 mAppDirs.put(pkg.mPath, pkg);
   3258             }
   3259             // Add the new setting to mSettings
   3260             mSettings.insertPackageSettingLP(pkgSetting, pkg);
   3261             // Add the new setting to mPackages
   3262             mPackages.put(pkg.applicationInfo.packageName, pkg);
   3263             // Make sure we don't accidentally delete its data.
   3264             mSettings.mPackagesToBeCleaned.remove(pkgName);
   3265 
   3266             int N = pkg.providers.size();
   3267             StringBuilder r = null;
   3268             int i;
   3269             for (i=0; i<N; i++) {
   3270                 PackageParser.Provider p = pkg.providers.get(i);
   3271                 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
   3272                         p.info.processName, pkg.applicationInfo.uid);
   3273                 mProvidersByComponent.put(new ComponentName(p.info.packageName,
   3274                         p.info.name), p);
   3275                 p.syncable = p.info.isSyncable;
   3276                 if (p.info.authority != null) {
   3277                     String names[] = p.info.authority.split(";");
   3278                     p.info.authority = null;
   3279                     for (int j = 0; j < names.length; j++) {
   3280                         if (j == 1 && p.syncable) {
   3281                             // We only want the first authority for a provider to possibly be
   3282                             // syncable, so if we already added this provider using a different
   3283                             // authority clear the syncable flag. We copy the provider before
   3284                             // changing it because the mProviders object contains a reference
   3285                             // to a provider that we don't want to change.
   3286                             // Only do this for the second authority since the resulting provider
   3287                             // object can be the same for all future authorities for this provider.
   3288                             p = new PackageParser.Provider(p);
   3289                             p.syncable = false;
   3290                         }
   3291                         if (!mProviders.containsKey(names[j])) {
   3292                             mProviders.put(names[j], p);
   3293                             if (p.info.authority == null) {
   3294                                 p.info.authority = names[j];
   3295                             } else {
   3296                                 p.info.authority = p.info.authority + ";" + names[j];
   3297                             }
   3298                             if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
   3299                                 Log.d(TAG, "Registered content provider: " + names[j] +
   3300                                         ", className = " + p.info.name +
   3301                                         ", isSyncable = " + p.info.isSyncable);
   3302                         } else {
   3303                             PackageParser.Provider other = mProviders.get(names[j]);
   3304                             Slog.w(TAG, "Skipping provider name " + names[j] +
   3305                                     " (in package " + pkg.applicationInfo.packageName +
   3306                                     "): name already used by "
   3307                                     + ((other != null && other.getComponentName() != null)
   3308                                             ? other.getComponentName().getPackageName() : "?"));
   3309                         }
   3310                     }
   3311                 }
   3312                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3313                     if (r == null) {
   3314                         r = new StringBuilder(256);
   3315                     } else {
   3316                         r.append(' ');
   3317                     }
   3318                     r.append(p.info.name);
   3319                 }
   3320             }
   3321             if (r != null) {
   3322                 if (Config.LOGD) Log.d(TAG, "  Providers: " + r);
   3323             }
   3324 
   3325             N = pkg.services.size();
   3326             r = null;
   3327             for (i=0; i<N; i++) {
   3328                 PackageParser.Service s = pkg.services.get(i);
   3329                 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
   3330                         s.info.processName, pkg.applicationInfo.uid);
   3331                 mServices.addService(s);
   3332                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3333                     if (r == null) {
   3334                         r = new StringBuilder(256);
   3335                     } else {
   3336                         r.append(' ');
   3337                     }
   3338                     r.append(s.info.name);
   3339                 }
   3340             }
   3341             if (r != null) {
   3342                 if (Config.LOGD) Log.d(TAG, "  Services: " + r);
   3343             }
   3344 
   3345             N = pkg.receivers.size();
   3346             r = null;
   3347             for (i=0; i<N; i++) {
   3348                 PackageParser.Activity a = pkg.receivers.get(i);
   3349                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
   3350                         a.info.processName, pkg.applicationInfo.uid);
   3351                 mReceivers.addActivity(a, "receiver");
   3352                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3353                     if (r == null) {
   3354                         r = new StringBuilder(256);
   3355                     } else {
   3356                         r.append(' ');
   3357                     }
   3358                     r.append(a.info.name);
   3359                 }
   3360             }
   3361             if (r != null) {
   3362                 if (Config.LOGD) Log.d(TAG, "  Receivers: " + r);
   3363             }
   3364 
   3365             N = pkg.activities.size();
   3366             r = null;
   3367             for (i=0; i<N; i++) {
   3368                 PackageParser.Activity a = pkg.activities.get(i);
   3369                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
   3370                         a.info.processName, pkg.applicationInfo.uid);
   3371                 mActivities.addActivity(a, "activity");
   3372                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3373                     if (r == null) {
   3374                         r = new StringBuilder(256);
   3375                     } else {
   3376                         r.append(' ');
   3377                     }
   3378                     r.append(a.info.name);
   3379                 }
   3380             }
   3381             if (r != null) {
   3382                 if (Config.LOGD) Log.d(TAG, "  Activities: " + r);
   3383             }
   3384 
   3385             N = pkg.permissionGroups.size();
   3386             r = null;
   3387             for (i=0; i<N; i++) {
   3388                 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
   3389                 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
   3390                 if (cur == null) {
   3391                     mPermissionGroups.put(pg.info.name, pg);
   3392                     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3393                         if (r == null) {
   3394                             r = new StringBuilder(256);
   3395                         } else {
   3396                             r.append(' ');
   3397                         }
   3398                         r.append(pg.info.name);
   3399                     }
   3400                 } else {
   3401                     Slog.w(TAG, "Permission group " + pg.info.name + " from package "
   3402                             + pg.info.packageName + " ignored: original from "
   3403                             + cur.info.packageName);
   3404                     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3405                         if (r == null) {
   3406                             r = new StringBuilder(256);
   3407                         } else {
   3408                             r.append(' ');
   3409                         }
   3410                         r.append("DUP:");
   3411                         r.append(pg.info.name);
   3412                     }
   3413                 }
   3414             }
   3415             if (r != null) {
   3416                 if (Config.LOGD) Log.d(TAG, "  Permission Groups: " + r);
   3417             }
   3418 
   3419             N = pkg.permissions.size();
   3420             r = null;
   3421             for (i=0; i<N; i++) {
   3422                 PackageParser.Permission p = pkg.permissions.get(i);
   3423                 HashMap<String, BasePermission> permissionMap =
   3424                         p.tree ? mSettings.mPermissionTrees
   3425                         : mSettings.mPermissions;
   3426                 p.group = mPermissionGroups.get(p.info.group);
   3427                 if (p.info.group == null || p.group != null) {
   3428                     BasePermission bp = permissionMap.get(p.info.name);
   3429                     if (bp == null) {
   3430                         bp = new BasePermission(p.info.name, p.info.packageName,
   3431                                 BasePermission.TYPE_NORMAL);
   3432                         permissionMap.put(p.info.name, bp);
   3433                     }
   3434                     if (bp.perm == null) {
   3435                         if (bp.sourcePackage == null
   3436                                 || bp.sourcePackage.equals(p.info.packageName)) {
   3437                             BasePermission tree = findPermissionTreeLP(p.info.name);
   3438                             if (tree == null
   3439                                     || tree.sourcePackage.equals(p.info.packageName)) {
   3440                                 bp.packageSetting = pkgSetting;
   3441                                 bp.perm = p;
   3442                                 bp.uid = pkg.applicationInfo.uid;
   3443                                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3444                                     if (r == null) {
   3445                                         r = new StringBuilder(256);
   3446                                     } else {
   3447                                         r.append(' ');
   3448                                     }
   3449                                     r.append(p.info.name);
   3450                                 }
   3451                             } else {
   3452                                 Slog.w(TAG, "Permission " + p.info.name + " from package "
   3453                                         + p.info.packageName + " ignored: base tree "
   3454                                         + tree.name + " is from package "
   3455                                         + tree.sourcePackage);
   3456                             }
   3457                         } else {
   3458                             Slog.w(TAG, "Permission " + p.info.name + " from package "
   3459                                     + p.info.packageName + " ignored: original from "
   3460                                     + bp.sourcePackage);
   3461                         }
   3462                     } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3463                         if (r == null) {
   3464                             r = new StringBuilder(256);
   3465                         } else {
   3466                             r.append(' ');
   3467                         }
   3468                         r.append("DUP:");
   3469                         r.append(p.info.name);
   3470                     }
   3471                     if (bp.perm == p) {
   3472                         bp.protectionLevel = p.info.protectionLevel;
   3473                     }
   3474                 } else {
   3475                     Slog.w(TAG, "Permission " + p.info.name + " from package "
   3476                             + p.info.packageName + " ignored: no group "
   3477                             + p.group);
   3478                 }
   3479             }
   3480             if (r != null) {
   3481                 if (Config.LOGD) Log.d(TAG, "  Permissions: " + r);
   3482             }
   3483 
   3484             N = pkg.instrumentation.size();
   3485             r = null;
   3486             for (i=0; i<N; i++) {
   3487                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
   3488                 a.info.packageName = pkg.applicationInfo.packageName;
   3489                 a.info.sourceDir = pkg.applicationInfo.sourceDir;
   3490                 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
   3491                 a.info.dataDir = pkg.applicationInfo.dataDir;
   3492                 mInstrumentation.put(a.getComponentName(), a);
   3493                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
   3494                     if (r == null) {
   3495                         r = new StringBuilder(256);
   3496                     } else {
   3497                         r.append(' ');
   3498                     }
   3499                     r.append(a.info.name);
   3500                 }
   3501             }
   3502             if (r != null) {
   3503                 if (Config.LOGD) Log.d(TAG, "  Instrumentation: " + r);
   3504             }
   3505 
   3506             if (pkg.protectedBroadcasts != null) {
   3507                 N = pkg.protectedBroadcasts.size();
   3508                 for (i=0; i<N; i++) {
   3509                     mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
   3510                 }
   3511             }
   3512 
   3513             pkgSetting.setTimeStamp(scanFileTime);
   3514         }
   3515 
   3516         return pkg;
   3517     }
   3518 
   3519     private void killApplication(String pkgName, int uid) {
   3520         // Request the ActivityManager to kill the process(only for existing packages)
   3521         // so that we do not end up in a confused state while the user is still using the older
   3522         // version of the application while the new one gets installed.
   3523         IActivityManager am = ActivityManagerNative.getDefault();
   3524         if (am != null) {
   3525             try {
   3526                 am.killApplicationWithUid(pkgName, uid);
   3527             } catch (RemoteException e) {
   3528             }
   3529         }
   3530     }
   3531 
   3532     // The following constants are returned by cachePackageSharedLibsForAbiLI
   3533     // to indicate if native shared libraries were found in the package.
   3534     // Values are:
   3535     //    PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
   3536     //    PACKAGE_INSTALL_NATIVE_NO_LIBRARIES     => no native libraries in package
   3537     //    PACKAGE_INSTALL_NATIVE_ABI_MISMATCH     => native libraries for another ABI found
   3538     //                                        in package (and not installed)
   3539     //
   3540     private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
   3541     private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
   3542     private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
   3543 
   3544     // Return the path of the directory that will contain the native binaries
   3545     // of a given installed package. This is relative to the data path.
   3546     //
   3547     private static File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
   3548         return new File(pkg.applicationInfo.dataDir + "/lib");
   3549     }
   3550 
   3551     // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
   3552     // and automatically copy them to /data/data/<appname>/lib if present.
   3553     //
   3554     // NOTE: this method may throw an IOException if the library cannot
   3555     // be copied to its final destination, e.g. if there isn't enough
   3556     // room left on the data partition, or a ZipException if the package
   3557     // file is malformed.
   3558     //
   3559     private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
   3560         File scanFile, String cpuAbi) throws IOException, ZipException {
   3561         File sharedLibraryDir = getNativeBinaryDirForPackage(pkg);
   3562         final String apkLib = "lib/";
   3563         final int apkLibLen = apkLib.length();
   3564         final int cpuAbiLen = cpuAbi.length();
   3565         final String libPrefix = "lib";
   3566         final int libPrefixLen = libPrefix.length();
   3567         final String libSuffix = ".so";
   3568         final int libSuffixLen = libSuffix.length();
   3569         boolean hasNativeLibraries = false;
   3570         boolean installedNativeLibraries = false;
   3571 
   3572         // the minimum length of a valid native shared library of the form
   3573         // lib/<something>/lib<name>.so.
   3574         final int minEntryLen  = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
   3575 
   3576         ZipFile zipFile = new ZipFile(scanFile);
   3577         Enumeration<ZipEntry> entries =
   3578             (Enumeration<ZipEntry>) zipFile.entries();
   3579 
   3580         while (entries.hasMoreElements()) {
   3581             ZipEntry entry = entries.nextElement();
   3582             // skip directories
   3583             if (entry.isDirectory()) {
   3584                 continue;
   3585             }
   3586             String entryName = entry.getName();
   3587 
   3588             // check that the entry looks like lib/<something>/lib<name>.so
   3589             // here, but don't check the ABI just yet.
   3590             //
   3591             // - must be sufficiently long
   3592             // - must end with libSuffix, i.e. ".so"
   3593             // - must start with apkLib, i.e. "lib/"
   3594             if (entryName.length() < minEntryLen ||
   3595                 !entryName.endsWith(libSuffix) ||
   3596                 !entryName.startsWith(apkLib) ) {
   3597                 continue;
   3598             }
   3599 
   3600             // file name must start with libPrefix, i.e. "lib"
   3601             int lastSlash = entryName.lastIndexOf('/');
   3602 
   3603             if (lastSlash < 0 ||
   3604                 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
   3605                 continue;
   3606             }
   3607 
   3608             hasNativeLibraries = true;
   3609 
   3610             // check the cpuAbi now, between lib/ and /lib<name>.so
   3611             //
   3612             if (lastSlash != apkLibLen + cpuAbiLen ||
   3613                 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
   3614                 continue;
   3615 
   3616             // extract the library file name, ensure it doesn't contain
   3617             // weird characters. we're guaranteed here that it doesn't contain
   3618             // a directory separator though.
   3619             String libFileName = entryName.substring(lastSlash+1);
   3620             if (!FileUtils.isFilenameSafe(new File(libFileName))) {
   3621                 continue;
   3622             }
   3623 
   3624             installedNativeLibraries = true;
   3625 
   3626             String sharedLibraryFilePath = sharedLibraryDir.getPath() +
   3627                 File.separator + libFileName;
   3628             File sharedLibraryFile = new File(sharedLibraryFilePath);
   3629             if (! sharedLibraryFile.exists() ||
   3630                 sharedLibraryFile.length() != entry.getSize() ||
   3631                 sharedLibraryFile.lastModified() != entry.getTime()) {
   3632                 if (Config.LOGD) {
   3633                     Log.d(TAG, "Caching shared lib " + entry.getName());
   3634                 }
   3635                 if (mInstaller == null) {
   3636                     sharedLibraryDir.mkdir();
   3637                 }
   3638                 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
   3639                         sharedLibraryFile);
   3640             }
   3641         }
   3642         if (!hasNativeLibraries)
   3643             return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
   3644 
   3645         if (!installedNativeLibraries)
   3646             return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
   3647 
   3648         return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
   3649     }
   3650 
   3651     // Find the gdbserver executable program in a package at
   3652     // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
   3653     //
   3654     // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
   3655     // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
   3656     //
   3657     private int cachePackageGdbServerLI(PackageParser.Package pkg,
   3658         File scanFile, String cpuAbi) throws IOException, ZipException {
   3659         File installGdbServerDir = getNativeBinaryDirForPackage(pkg);
   3660         final String GDBSERVER = "gdbserver";
   3661         final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
   3662 
   3663         ZipFile zipFile = new ZipFile(scanFile);
   3664         Enumeration<ZipEntry> entries =
   3665             (Enumeration<ZipEntry>) zipFile.entries();
   3666 
   3667         while (entries.hasMoreElements()) {
   3668             ZipEntry entry = entries.nextElement();
   3669             // skip directories
   3670             if (entry.isDirectory()) {
   3671                 continue;
   3672             }
   3673             String entryName = entry.getName();
   3674 
   3675             if (!entryName.equals(apkGdbServerPath)) {
   3676                 continue;
   3677             }
   3678 
   3679             String installGdbServerPath = installGdbServerDir.getPath() +
   3680                 "/" + GDBSERVER;
   3681             File installGdbServerFile = new File(installGdbServerPath);
   3682             if (! installGdbServerFile.exists() ||
   3683                 installGdbServerFile.length() != entry.getSize() ||
   3684                 installGdbServerFile.lastModified() != entry.getTime()) {
   3685                 if (Config.LOGD) {
   3686                     Log.d(TAG, "Caching gdbserver " + entry.getName());
   3687                 }
   3688                 if (mInstaller == null) {
   3689                     installGdbServerDir.mkdir();
   3690                 }
   3691                 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
   3692                         installGdbServerFile);
   3693             }
   3694             return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
   3695         }
   3696         return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
   3697     }
   3698 
   3699     // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
   3700     // and copy them to /data/data/<appname>/lib.
   3701     //
   3702     // This function will first try the main CPU ABI defined by Build.CPU_ABI
   3703     // (which corresponds to ro.product.cpu.abi), and also try an alternate
   3704     // one if ro.product.cpu.abi2 is defined.
   3705     //
   3706     private int cachePackageSharedLibsLI(PackageParser.Package pkg, File scanFile) {
   3707         String cpuAbi = Build.CPU_ABI;
   3708         try {
   3709             int result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi);
   3710 
   3711             // some architectures are capable of supporting several CPU ABIs
   3712             // for example, 'armeabi-v7a' also supports 'armeabi' native code
   3713             // this is indicated by the definition of the ro.product.cpu.abi2
   3714             // system property.
   3715             //
   3716             // only scan the package twice in case of ABI mismatch
   3717             if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
   3718                 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
   3719                 if (cpuAbi2 != null) {
   3720                     result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi2);
   3721                 }
   3722 
   3723                 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
   3724                     Slog.w(TAG,"Native ABI mismatch from package file");
   3725                     return PackageManager.INSTALL_FAILED_INVALID_APK;
   3726                 }
   3727 
   3728                 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
   3729                     cpuAbi = cpuAbi2;
   3730                 }
   3731             }
   3732 
   3733             // for debuggable packages, also extract gdbserver from lib/<abi>
   3734             // into /data/data/<appname>/lib too.
   3735             if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
   3736                 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
   3737                 int result2 = cachePackageGdbServerLI(pkg, scanFile, cpuAbi);
   3738                 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
   3739                     pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
   3740                 }
   3741             }
   3742         } catch (ZipException e) {
   3743             Slog.w(TAG, "Failed to extract data from package file", e);
   3744             return PackageManager.INSTALL_FAILED_INVALID_APK;
   3745         } catch (IOException e) {
   3746             Slog.w(TAG, "Failed to cache package shared libs", e);
   3747             return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   3748         }
   3749         return PackageManager.INSTALL_SUCCEEDED;
   3750     }
   3751 
   3752     private void cacheNativeBinaryLI(PackageParser.Package pkg,
   3753             ZipFile zipFile, ZipEntry entry,
   3754             File binaryDir,
   3755             File binaryFile) throws IOException {
   3756         InputStream inputStream = zipFile.getInputStream(entry);
   3757         try {
   3758             File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
   3759             String tempFilePath = tempFile.getPath();
   3760             // XXX package manager can't change owner, so the executable files for
   3761             // now need to be left as world readable and owned by the system.
   3762             if (! FileUtils.copyToFile(inputStream, tempFile) ||
   3763                 ! tempFile.setLastModified(entry.getTime()) ||
   3764                 FileUtils.setPermissions(tempFilePath,
   3765                         FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
   3766                         |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
   3767                         |FileUtils.S_IROTH, -1, -1) != 0 ||
   3768                 ! tempFile.renameTo(binaryFile)) {
   3769                 // Failed to properly write file.
   3770                 tempFile.delete();
   3771                 throw new IOException("Couldn't create cached binary "
   3772                         + binaryFile + " in " + binaryDir);
   3773             }
   3774         } finally {
   3775             inputStream.close();
   3776         }
   3777     }
   3778 
   3779     // Remove the native binaries of a given package. This simply
   3780     // gets rid of the files in the 'lib' sub-directory.
   3781     private void removeNativeBinariesLI(PackageParser.Package pkg) {
   3782         File binaryDir = getNativeBinaryDirForPackage(pkg);
   3783 
   3784         if (DEBUG_NATIVE) {
   3785             Slog.w(TAG,"Deleting native binaries from: " + binaryDir.getPath());
   3786         }
   3787 
   3788         // Just remove any file in the directory. Since the directory
   3789         // is owned by the 'system' UID, the application is not supposed
   3790         // to have written anything there.
   3791         //
   3792         if (binaryDir.exists()) {
   3793             File[]  binaries = binaryDir.listFiles();
   3794             if (binaries != null) {
   3795                 for (int nn=0; nn < binaries.length; nn++) {
   3796                     if (DEBUG_NATIVE) {
   3797                         Slog.d(TAG,"    Deleting " + binaries[nn].getName());
   3798                     }
   3799                     if (!binaries[nn].delete()) {
   3800                         Slog.w(TAG,"Could not delete native binary: " +
   3801                                 binaries[nn].getPath());
   3802                     }
   3803                 }
   3804             }
   3805             // Do not delete 'lib' directory itself, or this will prevent
   3806             // installation of future updates.
   3807         }
   3808     }
   3809 
   3810     void removePackageLI(PackageParser.Package pkg, boolean chatty) {
   3811         if (chatty && Config.LOGD) Log.d(
   3812             TAG, "Removing package " + pkg.applicationInfo.packageName );
   3813 
   3814         synchronized (mPackages) {
   3815             clearPackagePreferredActivitiesLP(pkg.packageName);
   3816 
   3817             mPackages.remove(pkg.applicationInfo.packageName);
   3818             if (pkg.mPath != null) {
   3819                 mAppDirs.remove(pkg.mPath);
   3820             }
   3821 
   3822             PackageSetting ps = (PackageSetting)pkg.mExtras;
   3823             if (ps != null && ps.sharedUser != null) {
   3824                 // XXX don't do this until the data is removed.
   3825                 if (false) {
   3826                     ps.sharedUser.packages.remove(ps);
   3827                     if (ps.sharedUser.packages.size() == 0) {
   3828                         // Remove.
   3829                     }
   3830                 }
   3831             }
   3832 
   3833             int N = pkg.providers.size();
   3834             StringBuilder r = null;
   3835             int i;
   3836             for (i=0; i<N; i++) {
   3837                 PackageParser.Provider p = pkg.providers.get(i);
   3838                 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
   3839                         p.info.name));
   3840                 if (p.info.authority == null) {
   3841 
   3842                     /* The is another ContentProvider with this authority when
   3843                      * this app was installed so this authority is null,
   3844                      * Ignore it as we don't have to unregister the provider.
   3845                      */
   3846                     continue;
   3847                 }
   3848                 String names[] = p.info.authority.split(";");
   3849                 for (int j = 0; j < names.length; j++) {
   3850                     if (mProviders.get(names[j]) == p) {
   3851                         mProviders.remove(names[j]);
   3852                         if (chatty && Config.LOGD) Log.d(
   3853                             TAG, "Unregistered content provider: " + names[j] +
   3854                             ", className = " + p.info.name +
   3855                             ", isSyncable = " + p.info.isSyncable);
   3856                     }
   3857                 }
   3858                 if (chatty) {
   3859                     if (r == null) {
   3860                         r = new StringBuilder(256);
   3861                     } else {
   3862                         r.append(' ');
   3863                     }
   3864                     r.append(p.info.name);
   3865                 }
   3866             }
   3867             if (r != null) {
   3868                 if (Config.LOGD) Log.d(TAG, "  Providers: " + r);
   3869             }
   3870 
   3871             N = pkg.services.size();
   3872             r = null;
   3873             for (i=0; i<N; i++) {
   3874                 PackageParser.Service s = pkg.services.get(i);
   3875                 mServices.removeService(s);
   3876                 if (chatty) {
   3877                     if (r == null) {
   3878                         r = new StringBuilder(256);
   3879                     } else {
   3880                         r.append(' ');
   3881                     }
   3882                     r.append(s.info.name);
   3883                 }
   3884             }
   3885             if (r != null) {
   3886                 if (Config.LOGD) Log.d(TAG, "  Services: " + r);
   3887             }
   3888 
   3889             N = pkg.receivers.size();
   3890             r = null;
   3891             for (i=0; i<N; i++) {
   3892                 PackageParser.Activity a = pkg.receivers.get(i);
   3893                 mReceivers.removeActivity(a, "receiver");
   3894                 if (chatty) {
   3895                     if (r == null) {
   3896                         r = new StringBuilder(256);
   3897                     } else {
   3898                         r.append(' ');
   3899                     }
   3900                     r.append(a.info.name);
   3901                 }
   3902             }
   3903             if (r != null) {
   3904                 if (Config.LOGD) Log.d(TAG, "  Receivers: " + r);
   3905             }
   3906 
   3907             N = pkg.activities.size();
   3908             r = null;
   3909             for (i=0; i<N; i++) {
   3910                 PackageParser.Activity a = pkg.activities.get(i);
   3911                 mActivities.removeActivity(a, "activity");
   3912                 if (chatty) {
   3913                     if (r == null) {
   3914                         r = new StringBuilder(256);
   3915                     } else {
   3916                         r.append(' ');
   3917                     }
   3918                     r.append(a.info.name);
   3919                 }
   3920             }
   3921             if (r != null) {
   3922                 if (Config.LOGD) Log.d(TAG, "  Activities: " + r);
   3923             }
   3924 
   3925             N = pkg.permissions.size();
   3926             r = null;
   3927             for (i=0; i<N; i++) {
   3928                 PackageParser.Permission p = pkg.permissions.get(i);
   3929                 boolean tree = false;
   3930                 BasePermission bp = mSettings.mPermissions.get(p.info.name);
   3931                 if (bp == null) {
   3932                     tree = true;
   3933                     bp = mSettings.mPermissionTrees.get(p.info.name);
   3934                 }
   3935                 if (bp != null && bp.perm == p) {
   3936                     bp.perm = null;
   3937                     if (chatty) {
   3938                         if (r == null) {
   3939                             r = new StringBuilder(256);
   3940                         } else {
   3941                             r.append(' ');
   3942                         }
   3943                         r.append(p.info.name);
   3944                     }
   3945                 }
   3946             }
   3947             if (r != null) {
   3948                 if (Config.LOGD) Log.d(TAG, "  Permissions: " + r);
   3949             }
   3950 
   3951             N = pkg.instrumentation.size();
   3952             r = null;
   3953             for (i=0; i<N; i++) {
   3954                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
   3955                 mInstrumentation.remove(a.getComponentName());
   3956                 if (chatty) {
   3957                     if (r == null) {
   3958                         r = new StringBuilder(256);
   3959                     } else {
   3960                         r.append(' ');
   3961                     }
   3962                     r.append(a.info.name);
   3963                 }
   3964             }
   3965             if (r != null) {
   3966                 if (Config.LOGD) Log.d(TAG, "  Instrumentation: " + r);
   3967             }
   3968         }
   3969     }
   3970 
   3971     private static final boolean isPackageFilename(String name) {
   3972         return name != null && name.endsWith(".apk");
   3973     }
   3974 
   3975     private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
   3976         for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
   3977             if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
   3978                 return true;
   3979             }
   3980         }
   3981         return false;
   3982     }
   3983 
   3984     private void updatePermissionsLP(String changingPkg,
   3985             PackageParser.Package pkgInfo, boolean grantPermissions,
   3986             boolean replace, boolean replaceAll) {
   3987         // Make sure there are no dangling permission trees.
   3988         Iterator<BasePermission> it = mSettings.mPermissionTrees
   3989                 .values().iterator();
   3990         while (it.hasNext()) {
   3991             BasePermission bp = it.next();
   3992             if (bp.packageSetting == null) {
   3993                 // We may not yet have parsed the package, so just see if
   3994                 // we still know about its settings.
   3995                 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
   3996             }
   3997             if (bp.packageSetting == null) {
   3998                 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
   3999                         + " from package " + bp.sourcePackage);
   4000                 it.remove();
   4001             } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
   4002                 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
   4003                     Slog.i(TAG, "Removing old permission tree: " + bp.name
   4004                             + " from package " + bp.sourcePackage);
   4005                     grantPermissions = true;
   4006                     it.remove();
   4007                 }
   4008             }
   4009         }
   4010 
   4011         // Make sure all dynamic permissions have been assigned to a package,
   4012         // and make sure there are no dangling permissions.
   4013         it = mSettings.mPermissions.values().iterator();
   4014         while (it.hasNext()) {
   4015             BasePermission bp = it.next();
   4016             if (bp.type == BasePermission.TYPE_DYNAMIC) {
   4017                 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
   4018                         + bp.name + " pkg=" + bp.sourcePackage
   4019                         + " info=" + bp.pendingInfo);
   4020                 if (bp.packageSetting == null && bp.pendingInfo != null) {
   4021                     BasePermission tree = findPermissionTreeLP(bp.name);
   4022                     if (tree != null) {
   4023                         bp.packageSetting = tree.packageSetting;
   4024                         bp.perm = new PackageParser.Permission(tree.perm.owner,
   4025                                 new PermissionInfo(bp.pendingInfo));
   4026                         bp.perm.info.packageName = tree.perm.info.packageName;
   4027                         bp.perm.info.name = bp.name;
   4028                         bp.uid = tree.uid;
   4029                     }
   4030                 }
   4031             }
   4032             if (bp.packageSetting == null) {
   4033                 // We may not yet have parsed the package, so just see if
   4034                 // we still know about its settings.
   4035                 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
   4036             }
   4037             if (bp.packageSetting == null) {
   4038                 Slog.w(TAG, "Removing dangling permission: " + bp.name
   4039                         + " from package " + bp.sourcePackage);
   4040                 it.remove();
   4041             } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
   4042                 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
   4043                     Slog.i(TAG, "Removing old permission: " + bp.name
   4044                             + " from package " + bp.sourcePackage);
   4045                     grantPermissions = true;
   4046                     it.remove();
   4047                 }
   4048             }
   4049         }
   4050 
   4051         // Now update the permissions for all packages, in particular
   4052         // replace the granted permissions of the system packages.
   4053         if (grantPermissions) {
   4054             for (PackageParser.Package pkg : mPackages.values()) {
   4055                 if (pkg != pkgInfo) {
   4056                     grantPermissionsLP(pkg, replaceAll);
   4057                 }
   4058             }
   4059         }
   4060 
   4061         if (pkgInfo != null) {
   4062             grantPermissionsLP(pkgInfo, replace);
   4063         }
   4064     }
   4065 
   4066     private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
   4067         final PackageSetting ps = (PackageSetting)pkg.mExtras;
   4068         if (ps == null) {
   4069             return;
   4070         }
   4071         final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
   4072         boolean changedPermission = false;
   4073 
   4074         if (replace) {
   4075             ps.permissionsFixed = false;
   4076             if (gp == ps) {
   4077                 gp.grantedPermissions.clear();
   4078                 gp.gids = mGlobalGids;
   4079             }
   4080         }
   4081 
   4082         if (gp.gids == null) {
   4083             gp.gids = mGlobalGids;
   4084         }
   4085 
   4086         final int N = pkg.requestedPermissions.size();
   4087         for (int i=0; i<N; i++) {
   4088             String name = pkg.requestedPermissions.get(i);
   4089             BasePermission bp = mSettings.mPermissions.get(name);
   4090             if (false) {
   4091                 if (gp != ps) {
   4092                     Log.i(TAG, "Package " + pkg.packageName + " checking " + name
   4093                             + ": " + bp);
   4094                 }
   4095             }
   4096             if (bp != null && bp.packageSetting != null) {
   4097                 final String perm = bp.name;
   4098                 boolean allowed;
   4099                 boolean allowedSig = false;
   4100                 if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL
   4101                         || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
   4102                     allowed = true;
   4103                 } else if (bp.packageSetting == null) {
   4104                     // This permission is invalid; skip it.
   4105                     allowed = false;
   4106                 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
   4107                         || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
   4108                     allowed = (checkSignaturesLP(bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
   4109                                     == PackageManager.SIGNATURE_MATCH)
   4110                             || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
   4111                                     == PackageManager.SIGNATURE_MATCH);
   4112                     if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
   4113                         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
   4114                             // For updated system applications, the signatureOrSystem permission
   4115                             // is granted only if it had been defined by the original application.
   4116                             if ((pkg.applicationInfo.flags
   4117                                     & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)  != 0) {
   4118                                 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
   4119                                 if(sysPs.grantedPermissions.contains(perm)) {
   4120                                     allowed = true;
   4121                                 } else {
   4122                                     allowed = false;
   4123                                 }
   4124                             } else {
   4125                                 allowed = true;
   4126                             }
   4127                         }
   4128                     }
   4129                     if (allowed) {
   4130                         allowedSig = true;
   4131                     }
   4132                 } else {
   4133                     allowed = false;
   4134                 }
   4135                 if (false) {
   4136                     if (gp != ps) {
   4137                         Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
   4138                     }
   4139                 }
   4140                 if (allowed) {
   4141                     if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
   4142                             && ps.permissionsFixed) {
   4143                         // If this is an existing, non-system package, then
   4144                         // we can't add any new permissions to it.
   4145                         if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
   4146                             allowed = false;
   4147                             // Except...  if this is a permission that was added
   4148                             // to the platform (note: need to only do this when
   4149                             // updating the platform).
   4150                             final int NP = PackageParser.NEW_PERMISSIONS.length;
   4151                             for (int ip=0; ip<NP; ip++) {
   4152                                 final PackageParser.NewPermissionInfo npi
   4153                                         = PackageParser.NEW_PERMISSIONS[ip];
   4154                                 if (npi.name.equals(perm)
   4155                                         && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
   4156                                     allowed = true;
   4157                                     Log.i(TAG, "Auto-granting " + perm + " to old pkg "
   4158                                             + pkg.packageName);
   4159                                     break;
   4160                                 }
   4161                             }
   4162                         }
   4163                     }
   4164                     if (allowed) {
   4165                         if (!gp.grantedPermissions.contains(perm)) {
   4166                             changedPermission = true;
   4167                             gp.grantedPermissions.add(perm);
   4168                             gp.gids = appendInts(gp.gids, bp.gids);
   4169                         } else if (!ps.haveGids) {
   4170                             gp.gids = appendInts(gp.gids, bp.gids);
   4171                         }
   4172                     } else {
   4173                         Slog.w(TAG, "Not granting permission " + perm
   4174                                 + " to package " + pkg.packageName
   4175                                 + " because it was previously installed without");
   4176                     }
   4177                 } else {
   4178                     if (gp.grantedPermissions.remove(perm)) {
   4179                         changedPermission = true;
   4180                         gp.gids = removeInts(gp.gids, bp.gids);
   4181                         Slog.i(TAG, "Un-granting permission " + perm
   4182                                 + " from package " + pkg.packageName
   4183                                 + " (protectionLevel=" + bp.protectionLevel
   4184                                 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
   4185                                 + ")");
   4186                     } else {
   4187                         Slog.w(TAG, "Not granting permission " + perm
   4188                                 + " to package " + pkg.packageName
   4189                                 + " (protectionLevel=" + bp.protectionLevel
   4190                                 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
   4191                                 + ")");
   4192                     }
   4193                 }
   4194             } else {
   4195                 Slog.w(TAG, "Unknown permission " + name
   4196                         + " in package " + pkg.packageName);
   4197             }
   4198         }
   4199 
   4200         if ((changedPermission || replace) && !ps.permissionsFixed &&
   4201                 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
   4202                 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
   4203             // This is the first that we have heard about this package, so the
   4204             // permissions we have now selected are fixed until explicitly
   4205             // changed.
   4206             ps.permissionsFixed = true;
   4207         }
   4208         ps.haveGids = true;
   4209     }
   4210 
   4211     private final class ActivityIntentResolver
   4212             extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
   4213         public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
   4214             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
   4215             return super.queryIntent(intent, resolvedType, defaultOnly);
   4216         }
   4217 
   4218         public List queryIntent(Intent intent, String resolvedType, int flags) {
   4219             mFlags = flags;
   4220             return super.queryIntent(intent, resolvedType,
   4221                 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
   4222         }
   4223 
   4224         public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
   4225                                           ArrayList<PackageParser.Activity> packageActivities) {
   4226             if (packageActivities == null) {
   4227                 return null;
   4228             }
   4229             mFlags = flags;
   4230             final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
   4231             int N = packageActivities.size();
   4232             ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
   4233                 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
   4234 
   4235             ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
   4236             for (int i = 0; i < N; ++i) {
   4237                 intentFilters = packageActivities.get(i).intents;
   4238                 if (intentFilters != null && intentFilters.size() > 0) {
   4239                     listCut.add(intentFilters);
   4240                 }
   4241             }
   4242             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
   4243         }
   4244 
   4245         public final void addActivity(PackageParser.Activity a, String type) {
   4246             mActivities.put(a.getComponentName(), a);
   4247             if (SHOW_INFO || Config.LOGV) Log.v(
   4248                 TAG, "  " + type + " " +
   4249                 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
   4250             if (SHOW_INFO || Config.LOGV) Log.v(TAG, "    Class=" + a.info.name);
   4251             int NI = a.intents.size();
   4252             for (int j=0; j<NI; j++) {
   4253                 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
   4254                 if (SHOW_INFO || Config.LOGV) {
   4255                     Log.v(TAG, "    IntentFilter:");
   4256                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
   4257                 }
   4258                 if (!intent.debugCheck()) {
   4259                     Log.w(TAG, "==> For Activity " + a.info.name);
   4260                 }
   4261                 addFilter(intent);
   4262             }
   4263         }
   4264 
   4265         public final void removeActivity(PackageParser.Activity a, String type) {
   4266             mActivities.remove(a.getComponentName());
   4267             if (SHOW_INFO || Config.LOGV) Log.v(
   4268                 TAG, "  " + type + " " +
   4269                 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
   4270             if (SHOW_INFO || Config.LOGV) Log.v(TAG, "    Class=" + a.info.name);
   4271             int NI = a.intents.size();
   4272             for (int j=0; j<NI; j++) {
   4273                 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
   4274                 if (SHOW_INFO || Config.LOGV) {
   4275                     Log.v(TAG, "    IntentFilter:");
   4276                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
   4277                 }
   4278                 removeFilter(intent);
   4279             }
   4280         }
   4281 
   4282         @Override
   4283         protected boolean allowFilterResult(
   4284                 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
   4285             ActivityInfo filterAi = filter.activity.info;
   4286             for (int i=dest.size()-1; i>=0; i--) {
   4287                 ActivityInfo destAi = dest.get(i).activityInfo;
   4288                 if (destAi.name == filterAi.name
   4289                         && destAi.packageName == filterAi.packageName) {
   4290                     return false;
   4291                 }
   4292             }
   4293             return true;
   4294         }
   4295 
   4296         @Override
   4297         protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
   4298             return info.activity.owner.packageName;
   4299         }
   4300 
   4301         @Override
   4302         protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
   4303                 int match) {
   4304             if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
   4305                 return null;
   4306             }
   4307             final PackageParser.Activity activity = info.activity;
   4308             if (mSafeMode && (activity.info.applicationInfo.flags
   4309                     &ApplicationInfo.FLAG_SYSTEM) == 0) {
   4310                 return null;
   4311             }
   4312             final ResolveInfo res = new ResolveInfo();
   4313             res.activityInfo = PackageParser.generateActivityInfo(activity,
   4314                     mFlags);
   4315             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
   4316                 res.filter = info;
   4317             }
   4318             res.priority = info.getPriority();
   4319             res.preferredOrder = activity.owner.mPreferredOrder;
   4320             //System.out.println("Result: " + res.activityInfo.className +
   4321             //                   " = " + res.priority);
   4322             res.match = match;
   4323             res.isDefault = info.hasDefault;
   4324             res.labelRes = info.labelRes;
   4325             res.nonLocalizedLabel = info.nonLocalizedLabel;
   4326             res.icon = info.icon;
   4327             return res;
   4328         }
   4329 
   4330         @Override
   4331         protected void sortResults(List<ResolveInfo> results) {
   4332             Collections.sort(results, mResolvePrioritySorter);
   4333         }
   4334 
   4335         @Override
   4336         protected void dumpFilter(PrintWriter out, String prefix,
   4337                 PackageParser.ActivityIntentInfo filter) {
   4338             out.print(prefix); out.print(
   4339                     Integer.toHexString(System.identityHashCode(filter.activity)));
   4340                     out.print(' ');
   4341                     out.print(filter.activity.getComponentShortName());
   4342                     out.print(" filter ");
   4343                     out.println(Integer.toHexString(System.identityHashCode(filter)));
   4344         }
   4345 
   4346 //        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
   4347 //            final Iterator<ResolveInfo> i = resolveInfoList.iterator();
   4348 //            final List<ResolveInfo> retList = Lists.newArrayList();
   4349 //            while (i.hasNext()) {
   4350 //                final ResolveInfo resolveInfo = i.next();
   4351 //                if (isEnabledLP(resolveInfo.activityInfo)) {
   4352 //                    retList.add(resolveInfo);
   4353 //                }
   4354 //            }
   4355 //            return retList;
   4356 //        }
   4357 
   4358         // Keys are String (activity class name), values are Activity.
   4359         private final HashMap<ComponentName, PackageParser.Activity> mActivities
   4360                 = new HashMap<ComponentName, PackageParser.Activity>();
   4361         private int mFlags;
   4362     }
   4363 
   4364     private final class ServiceIntentResolver
   4365             extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
   4366         public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
   4367             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
   4368             return super.queryIntent(intent, resolvedType, defaultOnly);
   4369         }
   4370 
   4371         public List queryIntent(Intent intent, String resolvedType, int flags) {
   4372             mFlags = flags;
   4373             return super.queryIntent(intent, resolvedType,
   4374                 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
   4375         }
   4376 
   4377         public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
   4378                                           ArrayList<PackageParser.Service> packageServices) {
   4379             if (packageServices == null) {
   4380                 return null;
   4381             }
   4382             mFlags = flags;
   4383             final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
   4384             int N = packageServices.size();
   4385             ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
   4386                 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
   4387 
   4388             ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
   4389             for (int i = 0; i < N; ++i) {
   4390                 intentFilters = packageServices.get(i).intents;
   4391                 if (intentFilters != null && intentFilters.size() > 0) {
   4392                     listCut.add(intentFilters);
   4393                 }
   4394             }
   4395             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
   4396         }
   4397 
   4398         public final void addService(PackageParser.Service s) {
   4399             mServices.put(s.getComponentName(), s);
   4400             if (SHOW_INFO || Config.LOGV) Log.v(
   4401                 TAG, "  " + (s.info.nonLocalizedLabel != null
   4402                         ? s.info.nonLocalizedLabel : s.info.name) + ":");
   4403             if (SHOW_INFO || Config.LOGV) Log.v(
   4404                     TAG, "    Class=" + s.info.name);
   4405             int NI = s.intents.size();
   4406             int j;
   4407             for (j=0; j<NI; j++) {
   4408                 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
   4409                 if (SHOW_INFO || Config.LOGV) {
   4410                     Log.v(TAG, "    IntentFilter:");
   4411                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
   4412                 }
   4413                 if (!intent.debugCheck()) {
   4414                     Log.w(TAG, "==> For Service " + s.info.name);
   4415                 }
   4416                 addFilter(intent);
   4417             }
   4418         }
   4419 
   4420         public final void removeService(PackageParser.Service s) {
   4421             mServices.remove(s.getComponentName());
   4422             if (SHOW_INFO || Config.LOGV) Log.v(
   4423                 TAG, "  " + (s.info.nonLocalizedLabel != null
   4424                         ? s.info.nonLocalizedLabel : s.info.name) + ":");
   4425             if (SHOW_INFO || Config.LOGV) Log.v(
   4426                     TAG, "    Class=" + s.info.name);
   4427             int NI = s.intents.size();
   4428             int j;
   4429             for (j=0; j<NI; j++) {
   4430                 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
   4431                 if (SHOW_INFO || Config.LOGV) {
   4432                     Log.v(TAG, "    IntentFilter:");
   4433                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
   4434                 }
   4435                 removeFilter(intent);
   4436             }
   4437         }
   4438 
   4439         @Override
   4440         protected boolean allowFilterResult(
   4441                 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
   4442             ServiceInfo filterSi = filter.service.info;
   4443             for (int i=dest.size()-1; i>=0; i--) {
   4444                 ServiceInfo destAi = dest.get(i).serviceInfo;
   4445                 if (destAi.name == filterSi.name
   4446                         && destAi.packageName == filterSi.packageName) {
   4447                     return false;
   4448                 }
   4449             }
   4450             return true;
   4451         }
   4452 
   4453         @Override
   4454         protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
   4455             return info.service.owner.packageName;
   4456         }
   4457 
   4458         @Override
   4459         protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
   4460                 int match) {
   4461             final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
   4462             if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
   4463                 return null;
   4464             }
   4465             final PackageParser.Service service = info.service;
   4466             if (mSafeMode && (service.info.applicationInfo.flags
   4467                     &ApplicationInfo.FLAG_SYSTEM) == 0) {
   4468                 return null;
   4469             }
   4470             final ResolveInfo res = new ResolveInfo();
   4471             res.serviceInfo = PackageParser.generateServiceInfo(service,
   4472                     mFlags);
   4473             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
   4474                 res.filter = filter;
   4475             }
   4476             res.priority = info.getPriority();
   4477             res.preferredOrder = service.owner.mPreferredOrder;
   4478             //System.out.println("Result: " + res.activityInfo.className +
   4479             //                   " = " + res.priority);
   4480             res.match = match;
   4481             res.isDefault = info.hasDefault;
   4482             res.labelRes = info.labelRes;
   4483             res.nonLocalizedLabel = info.nonLocalizedLabel;
   4484             res.icon = info.icon;
   4485             return res;
   4486         }
   4487 
   4488         @Override
   4489         protected void sortResults(List<ResolveInfo> results) {
   4490             Collections.sort(results, mResolvePrioritySorter);
   4491         }
   4492 
   4493         @Override
   4494         protected void dumpFilter(PrintWriter out, String prefix,
   4495                 PackageParser.ServiceIntentInfo filter) {
   4496             out.print(prefix); out.print(
   4497                     Integer.toHexString(System.identityHashCode(filter.service)));
   4498                     out.print(' ');
   4499                     out.print(filter.service.getComponentShortName());
   4500                     out.print(" filter ");
   4501                     out.println(Integer.toHexString(System.identityHashCode(filter)));
   4502         }
   4503 
   4504 //        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
   4505 //            final Iterator<ResolveInfo> i = resolveInfoList.iterator();
   4506 //            final List<ResolveInfo> retList = Lists.newArrayList();
   4507 //            while (i.hasNext()) {
   4508 //                final ResolveInfo resolveInfo = (ResolveInfo) i;
   4509 //                if (isEnabledLP(resolveInfo.serviceInfo)) {
   4510 //                    retList.add(resolveInfo);
   4511 //                }
   4512 //            }
   4513 //            return retList;
   4514 //        }
   4515 
   4516         // Keys are String (activity class name), values are Activity.
   4517         private final HashMap<ComponentName, PackageParser.Service> mServices
   4518                 = new HashMap<ComponentName, PackageParser.Service>();
   4519         private int mFlags;
   4520     };
   4521 
   4522     private static final Comparator<ResolveInfo> mResolvePrioritySorter =
   4523             new Comparator<ResolveInfo>() {
   4524         public int compare(ResolveInfo r1, ResolveInfo r2) {
   4525             int v1 = r1.priority;
   4526             int v2 = r2.priority;
   4527             //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
   4528             if (v1 != v2) {
   4529                 return (v1 > v2) ? -1 : 1;
   4530             }
   4531             v1 = r1.preferredOrder;
   4532             v2 = r2.preferredOrder;
   4533             if (v1 != v2) {
   4534                 return (v1 > v2) ? -1 : 1;
   4535             }
   4536             if (r1.isDefault != r2.isDefault) {
   4537                 return r1.isDefault ? -1 : 1;
   4538             }
   4539             v1 = r1.match;
   4540             v2 = r2.match;
   4541             //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
   4542             return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
   4543         }
   4544     };
   4545 
   4546     private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
   4547             new Comparator<ProviderInfo>() {
   4548         public int compare(ProviderInfo p1, ProviderInfo p2) {
   4549             final int v1 = p1.initOrder;
   4550             final int v2 = p2.initOrder;
   4551             return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
   4552         }
   4553     };
   4554 
   4555     private static final void sendPackageBroadcast(String action, String pkg,
   4556             Bundle extras, IIntentReceiver finishedReceiver) {
   4557         IActivityManager am = ActivityManagerNative.getDefault();
   4558         if (am != null) {
   4559             try {
   4560                 final Intent intent = new Intent(action,
   4561                         pkg != null ? Uri.fromParts("package", pkg, null) : null);
   4562                 if (extras != null) {
   4563                     intent.putExtras(extras);
   4564                 }
   4565                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   4566                 am.broadcastIntent(null, intent, null, finishedReceiver,
   4567                         0, null, null, null, finishedReceiver != null, false);
   4568             } catch (RemoteException ex) {
   4569             }
   4570         }
   4571     }
   4572 
   4573     public String nextPackageToClean(String lastPackage) {
   4574         synchronized (mPackages) {
   4575             if (!mMediaMounted) {
   4576                 // If the external storage is no longer mounted at this point,
   4577                 // the caller may not have been able to delete all of this
   4578                 // packages files and can not delete any more.  Bail.
   4579                 return null;
   4580             }
   4581             if (lastPackage != null) {
   4582                 mSettings.mPackagesToBeCleaned.remove(lastPackage);
   4583             }
   4584             return mSettings.mPackagesToBeCleaned.size() > 0
   4585                     ? mSettings.mPackagesToBeCleaned.get(0) : null;
   4586         }
   4587     }
   4588 
   4589     void schedulePackageCleaning(String packageName) {
   4590         mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
   4591     }
   4592 
   4593     void startCleaningPackages() {
   4594         synchronized (mPackages) {
   4595             if (!mMediaMounted) {
   4596                 return;
   4597             }
   4598             if (mSettings.mPackagesToBeCleaned.size() <= 0) {
   4599                 return;
   4600             }
   4601         }
   4602         Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
   4603         intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
   4604         IActivityManager am = ActivityManagerNative.getDefault();
   4605         if (am != null) {
   4606             try {
   4607                 am.startService(null, intent, null);
   4608             } catch (RemoteException e) {
   4609             }
   4610         }
   4611     }
   4612 
   4613     private final class AppDirObserver extends FileObserver {
   4614         public AppDirObserver(String path, int mask, boolean isrom) {
   4615             super(path, mask);
   4616             mRootDir = path;
   4617             mIsRom = isrom;
   4618         }
   4619 
   4620         public void onEvent(int event, String path) {
   4621             String removedPackage = null;
   4622             int removedUid = -1;
   4623             String addedPackage = null;
   4624             int addedUid = -1;
   4625 
   4626             synchronized (mInstallLock) {
   4627                 String fullPathStr = null;
   4628                 File fullPath = null;
   4629                 if (path != null) {
   4630                     fullPath = new File(mRootDir, path);
   4631                     fullPathStr = fullPath.getPath();
   4632                 }
   4633 
   4634                 if (Config.LOGV) Log.v(
   4635                     TAG, "File " + fullPathStr + " changed: "
   4636                     + Integer.toHexString(event));
   4637 
   4638                 if (!isPackageFilename(path)) {
   4639                     if (Config.LOGV) Log.v(
   4640                         TAG, "Ignoring change of non-package file: " + fullPathStr);
   4641                     return;
   4642                 }
   4643 
   4644                 // Ignore packages that are being installed or
   4645                 // have just been installed.
   4646                 if (ignoreCodePath(fullPathStr)) {
   4647                     return;
   4648                 }
   4649                 PackageParser.Package p = null;
   4650                 synchronized (mPackages) {
   4651                     p = mAppDirs.get(fullPathStr);
   4652                 }
   4653                 if ((event&REMOVE_EVENTS) != 0) {
   4654                     if (p != null) {
   4655                         removePackageLI(p, true);
   4656                         removedPackage = p.applicationInfo.packageName;
   4657                         removedUid = p.applicationInfo.uid;
   4658                     }
   4659                 }
   4660 
   4661                 if ((event&ADD_EVENTS) != 0) {
   4662                     if (p == null) {
   4663                         p = scanPackageLI(fullPath,
   4664                                 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
   4665                                         | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
   4666                                 PackageParser.PARSE_CHATTY |
   4667                                 PackageParser.PARSE_MUST_BE_APK,
   4668                                 SCAN_MONITOR | SCAN_NO_PATHS);
   4669                         if (p != null) {
   4670                             synchronized (mPackages) {
   4671                                 updatePermissionsLP(p.packageName, p,
   4672                                         p.permissions.size() > 0, false, false);
   4673                             }
   4674                             addedPackage = p.applicationInfo.packageName;
   4675                             addedUid = p.applicationInfo.uid;
   4676                         }
   4677                     }
   4678                 }
   4679 
   4680                 synchronized (mPackages) {
   4681                     mSettings.writeLP();
   4682                 }
   4683             }
   4684 
   4685             if (removedPackage != null) {
   4686                 Bundle extras = new Bundle(1);
   4687                 extras.putInt(Intent.EXTRA_UID, removedUid);
   4688                 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
   4689                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
   4690                         extras, null);
   4691             }
   4692             if (addedPackage != null) {
   4693                 Bundle extras = new Bundle(1);
   4694                 extras.putInt(Intent.EXTRA_UID, addedUid);
   4695                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
   4696                         extras, null);
   4697             }
   4698         }
   4699 
   4700         private final String mRootDir;
   4701         private final boolean mIsRom;
   4702     }
   4703 
   4704     /* Called when a downloaded package installation has been confirmed by the user */
   4705     public void installPackage(
   4706             final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
   4707         installPackage(packageURI, observer, flags, null);
   4708     }
   4709 
   4710     /* Called when a downloaded package installation has been confirmed by the user */
   4711     public void installPackage(
   4712             final Uri packageURI, final IPackageInstallObserver observer, final int flags,
   4713             final String installerPackageName) {
   4714         mContext.enforceCallingOrSelfPermission(
   4715                 android.Manifest.permission.INSTALL_PACKAGES, null);
   4716 
   4717         Message msg = mHandler.obtainMessage(INIT_COPY);
   4718         msg.obj = new InstallParams(packageURI, observer, flags,
   4719                 installerPackageName);
   4720         mHandler.sendMessage(msg);
   4721     }
   4722 
   4723     public void finishPackageInstall(int token) {
   4724         if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
   4725         Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
   4726         mHandler.sendMessage(msg);
   4727     }
   4728 
   4729     private void processPendingInstall(final InstallArgs args, final int currentStatus) {
   4730         // Queue up an async operation since the package installation may take a little while.
   4731         mHandler.post(new Runnable() {
   4732             public void run() {
   4733                 mHandler.removeCallbacks(this);
   4734                  // Result object to be returned
   4735                 PackageInstalledInfo res = new PackageInstalledInfo();
   4736                 res.returnCode = currentStatus;
   4737                 res.uid = -1;
   4738                 res.pkg = null;
   4739                 res.removedInfo = new PackageRemovedInfo();
   4740                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
   4741                     args.doPreInstall(res.returnCode);
   4742                     synchronized (mInstallLock) {
   4743                         installPackageLI(args, true, res);
   4744                     }
   4745                     args.doPostInstall(res.returnCode);
   4746                 }
   4747 
   4748                 // A restore should be performed at this point if (a) the install
   4749                 // succeeded, (b) the operation is not an update, and (c) the new
   4750                 // package has a backupAgent defined.
   4751                 final boolean update = res.removedInfo.removedPackage != null;
   4752                 boolean doRestore = (!update
   4753                         && res.pkg != null
   4754                         && res.pkg.applicationInfo.backupAgentName != null);
   4755 
   4756                 // Set up the post-install work request bookkeeping.  This will be used
   4757                 // and cleaned up by the post-install event handling regardless of whether
   4758                 // there's a restore pass performed.  Token values are >= 1.
   4759                 int token;
   4760                 if (mNextInstallToken < 0) mNextInstallToken = 1;
   4761                 token = mNextInstallToken++;
   4762 
   4763                 PostInstallData data = new PostInstallData(args, res);
   4764                 mRunningInstalls.put(token, data);
   4765                 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
   4766 
   4767                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
   4768                     // Pass responsibility to the Backup Manager.  It will perform a
   4769                     // restore if appropriate, then pass responsibility back to the
   4770                     // Package Manager to run the post-install observer callbacks
   4771                     // and broadcasts.
   4772                     IBackupManager bm = IBackupManager.Stub.asInterface(
   4773                             ServiceManager.getService(Context.BACKUP_SERVICE));
   4774                     if (bm != null) {
   4775                         if (DEBUG_INSTALL) Log.v(TAG, "token " + token
   4776                                 + " to BM for possible restore");
   4777                         try {
   4778                             bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
   4779                         } catch (RemoteException e) {
   4780                             // can't happen; the backup manager is local
   4781                         } catch (Exception e) {
   4782                             Slog.e(TAG, "Exception trying to enqueue restore", e);
   4783                             doRestore = false;
   4784                         }
   4785                     } else {
   4786                         Slog.e(TAG, "Backup Manager not found!");
   4787                         doRestore = false;
   4788                     }
   4789                 }
   4790 
   4791                 if (!doRestore) {
   4792                     // No restore possible, or the Backup Manager was mysteriously not
   4793                     // available -- just fire the post-install work request directly.
   4794                     if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
   4795                     Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
   4796                     mHandler.sendMessage(msg);
   4797                 }
   4798             }
   4799         });
   4800     }
   4801 
   4802     abstract class HandlerParams {
   4803         final static int MAX_RETRIES = 4;
   4804         int retry = 0;
   4805         final void startCopy() {
   4806             try {
   4807                 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
   4808                 retry++;
   4809                 if (retry > MAX_RETRIES) {
   4810                     Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
   4811                     mHandler.sendEmptyMessage(MCS_GIVE_UP);
   4812                     handleServiceError();
   4813                     return;
   4814                 } else {
   4815                     handleStartCopy();
   4816                     if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND");
   4817                     mHandler.sendEmptyMessage(MCS_UNBIND);
   4818                 }
   4819             } catch (RemoteException e) {
   4820                 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
   4821                 mHandler.sendEmptyMessage(MCS_RECONNECT);
   4822             }
   4823             handleReturnCode();
   4824         }
   4825 
   4826         final void serviceError() {
   4827             if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
   4828             handleServiceError();
   4829             handleReturnCode();
   4830         }
   4831         abstract void handleStartCopy() throws RemoteException;
   4832         abstract void handleServiceError();
   4833         abstract void handleReturnCode();
   4834     }
   4835 
   4836     class InstallParams extends HandlerParams {
   4837         final IPackageInstallObserver observer;
   4838         int flags;
   4839         final Uri packageURI;
   4840         final String installerPackageName;
   4841         private InstallArgs mArgs;
   4842         private int mRet;
   4843         InstallParams(Uri packageURI,
   4844                 IPackageInstallObserver observer, int flags,
   4845                 String installerPackageName) {
   4846             this.packageURI = packageURI;
   4847             this.flags = flags;
   4848             this.observer = observer;
   4849             this.installerPackageName = installerPackageName;
   4850         }
   4851 
   4852         private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
   4853             String packageName = pkgLite.packageName;
   4854             int installLocation = pkgLite.installLocation;
   4855             boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
   4856             synchronized (mPackages) {
   4857                 PackageParser.Package pkg = mPackages.get(packageName);
   4858                 if (pkg != null) {
   4859                     if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
   4860                         // Check for updated system application.
   4861                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
   4862                             if (onSd) {
   4863                                 Slog.w(TAG, "Cannot install update to system app on sdcard");
   4864                                 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
   4865                             }
   4866                             return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
   4867                         } else {
   4868                             if (onSd) {
   4869                                 // Install flag overrides everything.
   4870                                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
   4871                             }
   4872                             // If current upgrade specifies particular preference
   4873                             if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
   4874                                 // Application explicitly specified internal.
   4875                                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
   4876                             } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
   4877                                 // App explictly prefers external. Let policy decide
   4878                             } else {
   4879                                 // Prefer previous location
   4880                                 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
   4881                                     return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
   4882                                 }
   4883                                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
   4884                             }
   4885                         }
   4886                     } else {
   4887                         // Invalid install. Return error code
   4888                         return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
   4889                     }
   4890                 }
   4891             }
   4892             // All the special cases have been taken care of.
   4893             // Return result based on recommended install location.
   4894             if (onSd) {
   4895                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
   4896             }
   4897             return pkgLite.recommendedInstallLocation;
   4898         }
   4899 
   4900         /*
   4901          * Invoke remote method to get package information and install
   4902          * location values. Override install location based on default
   4903          * policy if needed and then create install arguments based
   4904          * on the install location.
   4905          */
   4906         public void handleStartCopy() throws RemoteException {
   4907             int ret = PackageManager.INSTALL_SUCCEEDED;
   4908             boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
   4909             boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
   4910             boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
   4911             if (onInt && onSd) {
   4912                 // Check if both bits are set.
   4913                 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
   4914                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
   4915             } else if (fwdLocked && onSd) {
   4916                 // Check for forward locked apps
   4917                 Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
   4918                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
   4919             } else {
   4920                 // Remote call to find out default install location
   4921                 PackageInfoLite pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
   4922                 int loc = pkgLite.recommendedInstallLocation;
   4923                 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
   4924                     ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
   4925                 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){
   4926                     ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
   4927                 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
   4928                     ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   4929                 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
   4930                     ret = PackageManager.INSTALL_FAILED_INVALID_APK;
   4931                 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
   4932                   ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
   4933                 } else {
   4934                     // Override with defaults if needed.
   4935                     loc = installLocationPolicy(pkgLite, flags);
   4936                     if (!onSd && !onInt) {
   4937                         // Override install location with flags
   4938                         if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
   4939                             // Set the flag to install on external media.
   4940                             flags |= PackageManager.INSTALL_EXTERNAL;
   4941                             flags &= ~PackageManager.INSTALL_INTERNAL;
   4942                         } else {
   4943                             // Make sure the flag for installing on external
   4944                             // media is unset
   4945                             flags |= PackageManager.INSTALL_INTERNAL;
   4946                             flags &= ~PackageManager.INSTALL_EXTERNAL;
   4947                         }
   4948                     }
   4949                 }
   4950             }
   4951             // Create the file args now.
   4952             mArgs = createInstallArgs(this);
   4953             if (ret == PackageManager.INSTALL_SUCCEEDED) {
   4954                 // Create copy only if we are not in an erroneous state.
   4955                 // Remote call to initiate copy using temporary file
   4956                 ret = mArgs.copyApk(mContainerService, true);
   4957             }
   4958             mRet = ret;
   4959         }
   4960 
   4961         @Override
   4962         void handleReturnCode() {
   4963             processPendingInstall(mArgs, mRet);
   4964         }
   4965 
   4966         @Override
   4967         void handleServiceError() {
   4968             mArgs = createInstallArgs(this);
   4969             mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
   4970         }
   4971     }
   4972 
   4973     /*
   4974      * Utility class used in movePackage api.
   4975      * srcArgs and targetArgs are not set for invalid flags and make
   4976      * sure to do null checks when invoking methods on them.
   4977      * We probably want to return ErrorPrams for both failed installs
   4978      * and moves.
   4979      */
   4980     class MoveParams extends HandlerParams {
   4981         final IPackageMoveObserver observer;
   4982         final int flags;
   4983         final String packageName;
   4984         final InstallArgs srcArgs;
   4985         final InstallArgs targetArgs;
   4986         int mRet;
   4987         MoveParams(InstallArgs srcArgs,
   4988                 IPackageMoveObserver observer,
   4989                 int flags, String packageName) {
   4990             this.srcArgs = srcArgs;
   4991             this.observer = observer;
   4992             this.flags = flags;
   4993             this.packageName = packageName;
   4994             if (srcArgs != null) {
   4995                 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
   4996                 targetArgs = createInstallArgs(packageUri, flags, packageName);
   4997             } else {
   4998                 targetArgs = null;
   4999             }
   5000         }
   5001 
   5002         public void handleStartCopy() throws RemoteException {
   5003             mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5004             // Check for storage space on target medium
   5005             if (!targetArgs.checkFreeStorage(mContainerService)) {
   5006                 Log.w(TAG, "Insufficient storage to install");
   5007                 return;
   5008             }
   5009             // Create the file args now.
   5010             mRet = targetArgs.copyApk(mContainerService, false);
   5011             targetArgs.doPreInstall(mRet);
   5012             if (DEBUG_SD_INSTALL) {
   5013                 StringBuilder builder = new StringBuilder();
   5014                 if (srcArgs != null) {
   5015                     builder.append("src: ");
   5016                     builder.append(srcArgs.getCodePath());
   5017                 }
   5018                 if (targetArgs != null) {
   5019                     builder.append(" target : ");
   5020                     builder.append(targetArgs.getCodePath());
   5021                 }
   5022                 Log.i(TAG, builder.toString());
   5023             }
   5024         }
   5025 
   5026         @Override
   5027         void handleReturnCode() {
   5028             targetArgs.doPostInstall(mRet);
   5029             int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
   5030             if (mRet == PackageManager.INSTALL_SUCCEEDED) {
   5031                 currentStatus = PackageManager.MOVE_SUCCEEDED;
   5032             } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
   5033                 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
   5034             }
   5035             processPendingMove(this, currentStatus);
   5036         }
   5037 
   5038         @Override
   5039         void handleServiceError() {
   5040             mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
   5041         }
   5042     }
   5043 
   5044     private InstallArgs createInstallArgs(InstallParams params) {
   5045         if (installOnSd(params.flags)) {
   5046             return new SdInstallArgs(params);
   5047         } else {
   5048             return new FileInstallArgs(params);
   5049         }
   5050     }
   5051 
   5052     private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
   5053         if (installOnSd(flags)) {
   5054             return new SdInstallArgs(fullCodePath, fullResourcePath);
   5055         } else {
   5056             return new FileInstallArgs(fullCodePath, fullResourcePath);
   5057         }
   5058     }
   5059 
   5060     private InstallArgs createInstallArgs(Uri packageURI, int flags,
   5061             String pkgName) {
   5062         if (installOnSd(flags)) {
   5063             String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
   5064             return new SdInstallArgs(packageURI, cid);
   5065         } else {
   5066             return new FileInstallArgs(packageURI, pkgName);
   5067         }
   5068     }
   5069 
   5070     static abstract class InstallArgs {
   5071         final IPackageInstallObserver observer;
   5072         // Always refers to PackageManager flags only
   5073         final int flags;
   5074         final Uri packageURI;
   5075         final String installerPackageName;
   5076 
   5077         InstallArgs(Uri packageURI,
   5078                 IPackageInstallObserver observer, int flags,
   5079                 String installerPackageName) {
   5080             this.packageURI = packageURI;
   5081             this.flags = flags;
   5082             this.observer = observer;
   5083             this.installerPackageName = installerPackageName;
   5084         }
   5085 
   5086         abstract void createCopyFile();
   5087         abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
   5088         abstract int doPreInstall(int status);
   5089         abstract boolean doRename(int status, String pkgName, String oldCodePath);
   5090         abstract int doPostInstall(int status);
   5091         abstract String getCodePath();
   5092         abstract String getResourcePath();
   5093         // Need installer lock especially for dex file removal.
   5094         abstract void cleanUpResourcesLI();
   5095         abstract boolean doPostDeleteLI(boolean delete);
   5096         abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
   5097     }
   5098 
   5099     class FileInstallArgs extends InstallArgs {
   5100         File installDir;
   5101         String codeFileName;
   5102         String resourceFileName;
   5103         boolean created = false;
   5104 
   5105         FileInstallArgs(InstallParams params) {
   5106             super(params.packageURI, params.observer,
   5107                     params.flags, params.installerPackageName);
   5108         }
   5109 
   5110         FileInstallArgs(String fullCodePath, String fullResourcePath) {
   5111             super(null, null, 0, null);
   5112             File codeFile = new File(fullCodePath);
   5113             installDir = codeFile.getParentFile();
   5114             codeFileName = fullCodePath;
   5115             resourceFileName = fullResourcePath;
   5116         }
   5117 
   5118         FileInstallArgs(Uri packageURI, String pkgName) {
   5119             super(packageURI, null, 0, null);
   5120             boolean fwdLocked = isFwdLocked(flags);
   5121             installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
   5122             String apkName = getNextCodePath(null, pkgName, ".apk");
   5123             codeFileName = new File(installDir, apkName + ".apk").getPath();
   5124             resourceFileName = getResourcePathFromCodePath();
   5125         }
   5126 
   5127         boolean  checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
   5128             return imcs.checkFreeStorage(false, packageURI);
   5129         }
   5130 
   5131         String getCodePath() {
   5132             return codeFileName;
   5133         }
   5134 
   5135         void createCopyFile() {
   5136             boolean fwdLocked = isFwdLocked(flags);
   5137             installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
   5138             codeFileName = createTempPackageFile(installDir).getPath();
   5139             resourceFileName = getResourcePathFromCodePath();
   5140             created = true;
   5141         }
   5142 
   5143         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
   5144             if (temp) {
   5145                 // Generate temp file name
   5146                 createCopyFile();
   5147             }
   5148             // Get a ParcelFileDescriptor to write to the output file
   5149             File codeFile = new File(codeFileName);
   5150             if (!created) {
   5151                 try {
   5152                     codeFile.createNewFile();
   5153                     // Set permissions
   5154                     if (!setPermissions()) {
   5155                         // Failed setting permissions.
   5156                         return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5157                     }
   5158                 } catch (IOException e) {
   5159                    Slog.w(TAG, "Failed to create file " + codeFile);
   5160                    return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5161                 }
   5162             }
   5163             ParcelFileDescriptor out = null;
   5164             try {
   5165             out = ParcelFileDescriptor.open(codeFile,
   5166                     ParcelFileDescriptor.MODE_READ_WRITE);
   5167             } catch (FileNotFoundException e) {
   5168                 Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
   5169                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5170             }
   5171             // Copy the resource now
   5172             int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5173             try {
   5174                 if (imcs.copyResource(packageURI, out)) {
   5175                     ret = PackageManager.INSTALL_SUCCEEDED;
   5176                 }
   5177             } finally {
   5178                 try { if (out != null) out.close(); } catch (IOException e) {}
   5179             }
   5180             return ret;
   5181         }
   5182 
   5183         int doPreInstall(int status) {
   5184             if (status != PackageManager.INSTALL_SUCCEEDED) {
   5185                 cleanUp();
   5186             }
   5187             return status;
   5188         }
   5189 
   5190         boolean doRename(int status, final String pkgName, String oldCodePath) {
   5191             if (status != PackageManager.INSTALL_SUCCEEDED) {
   5192                 cleanUp();
   5193                 return false;
   5194             } else {
   5195                 // Rename based on packageName
   5196                 File codeFile = new File(getCodePath());
   5197                 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
   5198                 File desFile = new File(installDir, apkName + ".apk");
   5199                 if (!codeFile.renameTo(desFile)) {
   5200                     return false;
   5201                 }
   5202                 // Reset paths since the file has been renamed.
   5203                 codeFileName = desFile.getPath();
   5204                 resourceFileName = getResourcePathFromCodePath();
   5205                 // Set permissions
   5206                 if (!setPermissions()) {
   5207                     // Failed setting permissions.
   5208                     return false;
   5209                 }
   5210                 return true;
   5211             }
   5212         }
   5213 
   5214         int doPostInstall(int status) {
   5215             if (status != PackageManager.INSTALL_SUCCEEDED) {
   5216                 cleanUp();
   5217             }
   5218             return status;
   5219         }
   5220 
   5221         String getResourcePath() {
   5222             return resourceFileName;
   5223         }
   5224 
   5225         String getResourcePathFromCodePath() {
   5226             String codePath = getCodePath();
   5227             if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
   5228                 String apkNameOnly = getApkName(codePath);
   5229                 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
   5230             } else {
   5231                 return codePath;
   5232             }
   5233         }
   5234 
   5235         private boolean cleanUp() {
   5236             boolean ret = true;
   5237             String sourceDir = getCodePath();
   5238             String publicSourceDir = getResourcePath();
   5239             if (sourceDir != null) {
   5240                 File sourceFile = new File(sourceDir);
   5241                 if (!sourceFile.exists()) {
   5242                     Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
   5243                     ret = false;
   5244                 }
   5245                 // Delete application's code and resources
   5246                 sourceFile.delete();
   5247             }
   5248             if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
   5249                 final File publicSourceFile = new File(publicSourceDir);
   5250                 if (!publicSourceFile.exists()) {
   5251                     Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
   5252                 }
   5253                 if (publicSourceFile.exists()) {
   5254                     publicSourceFile.delete();
   5255                 }
   5256             }
   5257             return ret;
   5258         }
   5259 
   5260         void cleanUpResourcesLI() {
   5261             String sourceDir = getCodePath();
   5262             if (cleanUp() && mInstaller != null) {
   5263                 int retCode = mInstaller.rmdex(sourceDir);
   5264                 if (retCode < 0) {
   5265                     Slog.w(TAG, "Couldn't remove dex file for package: "
   5266                             +  " at location "
   5267                             + sourceDir + ", retcode=" + retCode);
   5268                     // we don't consider this to be a failure of the core package deletion
   5269                 }
   5270             }
   5271         }
   5272 
   5273         private boolean setPermissions() {
   5274             // TODO Do this in a more elegant way later on. for now just a hack
   5275             if (!isFwdLocked(flags)) {
   5276                 final int filePermissions =
   5277                     FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
   5278                     |FileUtils.S_IROTH;
   5279                 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
   5280                 if (retCode != 0) {
   5281                     Slog.e(TAG, "Couldn't set new package file permissions for " +
   5282                             getCodePath()
   5283                             + ". The return code was: " + retCode);
   5284                     // TODO Define new internal error
   5285                     return false;
   5286                 }
   5287                 return true;
   5288             }
   5289             return true;
   5290         }
   5291 
   5292         boolean doPostDeleteLI(boolean delete) {
   5293             cleanUpResourcesLI();
   5294             return true;
   5295         }
   5296     }
   5297 
   5298     class SdInstallArgs extends InstallArgs {
   5299         String cid;
   5300         String cachePath;
   5301         static final String RES_FILE_NAME = "pkg.apk";
   5302 
   5303         SdInstallArgs(InstallParams params) {
   5304             super(params.packageURI, params.observer,
   5305                     params.flags, params.installerPackageName);
   5306         }
   5307 
   5308         SdInstallArgs(String fullCodePath, String fullResourcePath) {
   5309             super(null, null, PackageManager.INSTALL_EXTERNAL, null);
   5310             // Extract cid from fullCodePath
   5311             int eidx = fullCodePath.lastIndexOf("/");
   5312             String subStr1 = fullCodePath.substring(0, eidx);
   5313             int sidx = subStr1.lastIndexOf("/");
   5314             cid = subStr1.substring(sidx+1, eidx);
   5315             cachePath = subStr1;
   5316         }
   5317 
   5318         SdInstallArgs(String cid) {
   5319             super(null, null, PackageManager.INSTALL_EXTERNAL, null);
   5320             this.cid = cid;
   5321             cachePath = PackageHelper.getSdDir(cid);
   5322         }
   5323 
   5324         SdInstallArgs(Uri packageURI, String cid) {
   5325             super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
   5326             this.cid = cid;
   5327         }
   5328 
   5329         void createCopyFile() {
   5330             cid = getTempContainerId();
   5331         }
   5332 
   5333         boolean  checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
   5334             return imcs.checkFreeStorage(true, packageURI);
   5335         }
   5336 
   5337         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
   5338             if (temp) {
   5339                 createCopyFile();
   5340             }
   5341             cachePath = imcs.copyResourceToContainer(
   5342                     packageURI, cid,
   5343                     getEncryptKey(), RES_FILE_NAME);
   5344             return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
   5345                 PackageManager.INSTALL_SUCCEEDED;
   5346         }
   5347 
   5348         @Override
   5349         String getCodePath() {
   5350             return cachePath + "/" + RES_FILE_NAME;
   5351         }
   5352 
   5353         @Override
   5354         String getResourcePath() {
   5355             return cachePath + "/" + RES_FILE_NAME;
   5356         }
   5357 
   5358         int doPreInstall(int status) {
   5359             if (status != PackageManager.INSTALL_SUCCEEDED) {
   5360                 // Destroy container
   5361                 PackageHelper.destroySdDir(cid);
   5362             } else {
   5363                 boolean mounted = PackageHelper.isContainerMounted(cid);
   5364                 if (!mounted) {
   5365                     cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
   5366                     if (cachePath == null) {
   5367                         return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
   5368                     }
   5369                 }
   5370             }
   5371             return status;
   5372         }
   5373 
   5374         boolean doRename(int status, final String pkgName,
   5375                 String oldCodePath) {
   5376             String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
   5377             String newCachePath = null;
   5378             if (PackageHelper.isContainerMounted(cid)) {
   5379                 // Unmount the container
   5380                 if (!PackageHelper.unMountSdDir(cid)) {
   5381                     Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
   5382                     return false;
   5383                 }
   5384             }
   5385             if (!PackageHelper.renameSdDir(cid, newCacheId)) {
   5386                 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
   5387                         " which might be stale. Will try to clean up.");
   5388                 // Clean up the stale container and proceed to recreate.
   5389                 if (!PackageHelper.destroySdDir(newCacheId)) {
   5390                     Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
   5391                     return false;
   5392                 }
   5393                 // Successfully cleaned up stale container. Try to rename again.
   5394                 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
   5395                     Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
   5396                             + " inspite of cleaning it up.");
   5397                     return false;
   5398                 }
   5399             }
   5400             if (!PackageHelper.isContainerMounted(newCacheId)) {
   5401                 Slog.w(TAG, "Mounting container " + newCacheId);
   5402                 newCachePath = PackageHelper.mountSdDir(newCacheId,
   5403                         getEncryptKey(), Process.SYSTEM_UID);
   5404             } else {
   5405                 newCachePath = PackageHelper.getSdDir(newCacheId);
   5406             }
   5407             if (newCachePath == null) {
   5408                 Slog.w(TAG, "Failed to get cache path for  " + newCacheId);
   5409                 return false;
   5410             }
   5411             Log.i(TAG, "Succesfully renamed " + cid +
   5412                     " at path: " + cachePath + " to " + newCacheId +
   5413                     " at new path: " + newCachePath);
   5414             cid = newCacheId;
   5415             cachePath = newCachePath;
   5416             return true;
   5417         }
   5418 
   5419         int doPostInstall(int status) {
   5420             if (status != PackageManager.INSTALL_SUCCEEDED) {
   5421                 cleanUp();
   5422             } else {
   5423                 boolean mounted = PackageHelper.isContainerMounted(cid);
   5424                 if (!mounted) {
   5425                     PackageHelper.mountSdDir(cid,
   5426                             getEncryptKey(), Process.myUid());
   5427                 }
   5428             }
   5429             return status;
   5430         }
   5431 
   5432         private void cleanUp() {
   5433             // Destroy secure container
   5434             PackageHelper.destroySdDir(cid);
   5435         }
   5436 
   5437         void cleanUpResourcesLI() {
   5438             String sourceFile = getCodePath();
   5439             // Remove dex file
   5440             if (mInstaller != null) {
   5441                 int retCode = mInstaller.rmdex(sourceFile);
   5442                 if (retCode < 0) {
   5443                     Slog.w(TAG, "Couldn't remove dex file for package: "
   5444                             + " at location "
   5445                             + sourceFile.toString() + ", retcode=" + retCode);
   5446                     // we don't consider this to be a failure of the core package deletion
   5447                 }
   5448             }
   5449             cleanUp();
   5450         }
   5451 
   5452         boolean matchContainer(String app) {
   5453             if (cid.startsWith(app)) {
   5454                 return true;
   5455             }
   5456             return false;
   5457         }
   5458 
   5459         String getPackageName() {
   5460             int idx = cid.lastIndexOf("-");
   5461             if (idx == -1) {
   5462                 return cid;
   5463             }
   5464             return cid.substring(0, idx);
   5465         }
   5466 
   5467         boolean doPostDeleteLI(boolean delete) {
   5468             boolean ret = false;
   5469             boolean mounted = PackageHelper.isContainerMounted(cid);
   5470             if (mounted) {
   5471                 // Unmount first
   5472                 ret = PackageHelper.unMountSdDir(cid);
   5473             }
   5474             if (ret && delete) {
   5475                 cleanUpResourcesLI();
   5476             }
   5477             return ret;
   5478         }
   5479     };
   5480 
   5481     // Utility method used to create code paths based on package name and available index.
   5482     private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
   5483         String idxStr = "";
   5484         int idx = 1;
   5485         // Fall back to default value of idx=1 if prefix is not
   5486         // part of oldCodePath
   5487         if (oldCodePath != null) {
   5488             String subStr = oldCodePath;
   5489             // Drop the suffix right away
   5490             if (subStr.endsWith(suffix)) {
   5491                 subStr = subStr.substring(0, subStr.length() - suffix.length());
   5492             }
   5493             // If oldCodePath already contains prefix find out the
   5494             // ending index to either increment or decrement.
   5495             int sidx = subStr.lastIndexOf(prefix);
   5496             if (sidx != -1) {
   5497                 subStr = subStr.substring(sidx + prefix.length());
   5498                 if (subStr != null) {
   5499                     if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
   5500                         subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
   5501                     }
   5502                     try {
   5503                         idx = Integer.parseInt(subStr);
   5504                         if (idx <= 1) {
   5505                             idx++;
   5506                         } else {
   5507                             idx--;
   5508                         }
   5509                     } catch(NumberFormatException e) {
   5510                     }
   5511                 }
   5512             }
   5513         }
   5514         idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
   5515         return prefix + idxStr;
   5516     }
   5517 
   5518     // Utility method used to ignore ADD/REMOVE events
   5519     // by directory observer.
   5520     private static boolean ignoreCodePath(String fullPathStr) {
   5521         String apkName = getApkName(fullPathStr);
   5522         int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
   5523         if (idx != -1 && ((idx+1) < apkName.length())) {
   5524             // Make sure the package ends with a numeral
   5525             String version = apkName.substring(idx+1);
   5526             try {
   5527                 Integer.parseInt(version);
   5528                 return true;
   5529             } catch (NumberFormatException e) {}
   5530         }
   5531         return false;
   5532     }
   5533 
   5534     // Utility method that returns the relative package path with respect
   5535     // to the installation directory. Like say for /data/data/com.test-1.apk
   5536     // string com.test-1 is returned.
   5537     static String getApkName(String codePath) {
   5538         if (codePath == null) {
   5539             return null;
   5540         }
   5541         int sidx = codePath.lastIndexOf("/");
   5542         int eidx = codePath.lastIndexOf(".");
   5543         if (eidx == -1) {
   5544             eidx = codePath.length();
   5545         } else if (eidx == 0) {
   5546             Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
   5547             return null;
   5548         }
   5549         return codePath.substring(sidx+1, eidx);
   5550     }
   5551 
   5552     class PackageInstalledInfo {
   5553         String name;
   5554         int uid;
   5555         PackageParser.Package pkg;
   5556         int returnCode;
   5557         PackageRemovedInfo removedInfo;
   5558     }
   5559 
   5560     /*
   5561      * Install a non-existing package.
   5562      */
   5563     private void installNewPackageLI(PackageParser.Package pkg,
   5564             int parseFlags,
   5565             int scanMode,
   5566             String installerPackageName, PackageInstalledInfo res) {
   5567         // Remember this for later, in case we need to rollback this install
   5568         String pkgName = pkg.packageName;
   5569 
   5570         boolean dataDirExists = getDataPathForPackage(pkg).exists();
   5571         res.name = pkgName;
   5572         synchronized(mPackages) {
   5573             if (mSettings.mRenamedPackages.containsKey(pkgName)) {
   5574                 // A package with the same name is already installed, though
   5575                 // it has been renamed to an older name.  The package we
   5576                 // are trying to install should be installed as an update to
   5577                 // the existing one, but that has not been requested, so bail.
   5578                 Slog.w(TAG, "Attempt to re-install " + pkgName
   5579                         + " without first uninstalling package running as "
   5580                         + mSettings.mRenamedPackages.get(pkgName));
   5581                 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
   5582                 return;
   5583             }
   5584             if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
   5585                 // Don't allow installation over an existing package with the same name.
   5586                 Slog.w(TAG, "Attempt to re-install " + pkgName
   5587                         + " without first uninstalling.");
   5588                 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
   5589                 return;
   5590             }
   5591         }
   5592         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
   5593         PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
   5594         if (newPackage == null) {
   5595             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
   5596             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
   5597                 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
   5598             }
   5599         } else {
   5600             updateSettingsLI(newPackage,
   5601                     installerPackageName,
   5602                     res);
   5603             // delete the partially installed application. the data directory will have to be
   5604             // restored if it was already existing
   5605             if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
   5606                 // remove package from internal structures.  Note that we want deletePackageX to
   5607                 // delete the package data and cache directories that it created in
   5608                 // scanPackageLocked, unless those directories existed before we even tried to
   5609                 // install.
   5610                 deletePackageLI(
   5611                         pkgName, false,
   5612                         dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
   5613                                 res.removedInfo);
   5614             }
   5615         }
   5616     }
   5617 
   5618     private void replacePackageLI(PackageParser.Package pkg,
   5619             int parseFlags,
   5620             int scanMode,
   5621             String installerPackageName, PackageInstalledInfo res) {
   5622 
   5623         PackageParser.Package oldPackage;
   5624         String pkgName = pkg.packageName;
   5625         // First find the old package info and check signatures
   5626         synchronized(mPackages) {
   5627             oldPackage = mPackages.get(pkgName);
   5628             if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures)
   5629                     != PackageManager.SIGNATURE_MATCH) {
   5630                 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
   5631                 return;
   5632             }
   5633         }
   5634         boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
   5635         if (sysPkg) {
   5636             replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
   5637         } else {
   5638             replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
   5639         }
   5640     }
   5641 
   5642     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
   5643             PackageParser.Package pkg,
   5644             int parseFlags, int scanMode,
   5645             String installerPackageName, PackageInstalledInfo res) {
   5646         PackageParser.Package newPackage = null;
   5647         String pkgName = deletedPackage.packageName;
   5648         boolean deletedPkg = true;
   5649         boolean updatedSettings = false;
   5650 
   5651         String oldInstallerPackageName = null;
   5652         synchronized (mPackages) {
   5653             oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
   5654         }
   5655 
   5656         // First delete the existing package while retaining the data directory
   5657         if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
   5658                 res.removedInfo)) {
   5659             // If the existing package was'nt successfully deleted
   5660             res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
   5661             deletedPkg = false;
   5662         } else {
   5663             // Successfully deleted the old package. Now proceed with re-installation
   5664             mLastScanError = PackageManager.INSTALL_SUCCEEDED;
   5665             newPackage = scanPackageLI(pkg, parseFlags, scanMode);
   5666             if (newPackage == null) {
   5667                 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
   5668                 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
   5669                     res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
   5670                 }
   5671             } else {
   5672                 updateSettingsLI(newPackage,
   5673                         installerPackageName,
   5674                         res);
   5675                 updatedSettings = true;
   5676             }
   5677         }
   5678 
   5679         if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
   5680             // remove package from internal structures.  Note that we want deletePackageX to
   5681             // delete the package data and cache directories that it created in
   5682             // scanPackageLocked, unless those directories existed before we even tried to
   5683             // install.
   5684             if(updatedSettings) {
   5685                 deletePackageLI(
   5686                         pkgName, true,
   5687                         PackageManager.DONT_DELETE_DATA,
   5688                                 res.removedInfo);
   5689             }
   5690             // Since we failed to install the new package we need to restore the old
   5691             // package that we deleted.
   5692             if(deletedPkg) {
   5693                 File restoreFile = new File(deletedPackage.mPath);
   5694                 if (restoreFile == null) {
   5695                     Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
   5696                     return;
   5697                 }
   5698                 // Parse old package
   5699                 boolean oldOnSd = isExternal(deletedPackage);
   5700                 int oldParseFlags  = mDefParseFlags | PackageParser.PARSE_CHATTY |
   5701                         (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
   5702                         (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
   5703                 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE;
   5704                 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode) == null) {
   5705                     Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
   5706                     return;
   5707                 }
   5708                 // Restore of old package succeeded. Update permissions.
   5709                 synchronized (mPackages) {
   5710                     updatePermissionsLP(deletedPackage.packageName, deletedPackage,
   5711                             true, false, false);
   5712                     mSettings.writeLP();
   5713                 }
   5714                 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
   5715             }
   5716         }
   5717     }
   5718 
   5719     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
   5720             PackageParser.Package pkg,
   5721             int parseFlags, int scanMode,
   5722             String installerPackageName, PackageInstalledInfo res) {
   5723         PackageParser.Package newPackage = null;
   5724         boolean updatedSettings = false;
   5725         parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
   5726                 PackageParser.PARSE_IS_SYSTEM;
   5727         String packageName = deletedPackage.packageName;
   5728         res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
   5729         if (packageName == null) {
   5730             Slog.w(TAG, "Attempt to delete null packageName.");
   5731             return;
   5732         }
   5733         PackageParser.Package oldPkg;
   5734         PackageSetting oldPkgSetting;
   5735         synchronized (mPackages) {
   5736             oldPkg = mPackages.get(packageName);
   5737             oldPkgSetting = mSettings.mPackages.get(packageName);
   5738             if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
   5739                     (oldPkgSetting == null)) {
   5740                 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
   5741                 return;
   5742             }
   5743         }
   5744         res.removedInfo.uid = oldPkg.applicationInfo.uid;
   5745         res.removedInfo.removedPackage = packageName;
   5746         // Remove existing system package
   5747         removePackageLI(oldPkg, true);
   5748         synchronized (mPackages) {
   5749             res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
   5750         }
   5751 
   5752         // Successfully disabled the old package. Now proceed with re-installation
   5753         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
   5754         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
   5755         newPackage = scanPackageLI(pkg, parseFlags, scanMode);
   5756         if (newPackage == null) {
   5757             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
   5758             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
   5759                 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
   5760             }
   5761         } else {
   5762             updateSettingsLI(newPackage, installerPackageName, res);
   5763             updatedSettings = true;
   5764         }
   5765 
   5766         if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
   5767             // Re installation failed. Restore old information
   5768             // Remove new pkg information
   5769             if (newPackage != null) {
   5770                 removePackageLI(newPackage, true);
   5771             }
   5772             // Add back the old system package
   5773             scanPackageLI(oldPkg, parseFlags,
   5774                     SCAN_MONITOR
   5775                     | SCAN_UPDATE_SIGNATURE);
   5776             // Restore the old system information in Settings
   5777             synchronized(mPackages) {
   5778                 if(updatedSettings) {
   5779                     mSettings.enableSystemPackageLP(packageName);
   5780                     mSettings.setInstallerPackageName(packageName,
   5781                             oldPkgSetting.installerPackageName);
   5782                 }
   5783                 mSettings.writeLP();
   5784             }
   5785         } else {
   5786             // If this is an update to an existing update, setup
   5787             // to remove the existing update.
   5788             synchronized (mPackages) {
   5789                 PackageSetting ps = mSettings.getDisabledSystemPkg(packageName);
   5790                 if (ps != null && ps.codePathString != null &&
   5791                         !ps.codePathString.equals(oldPkgSetting.codePathString)) {
   5792                     int installFlags = 0;
   5793                     res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
   5794                             oldPkgSetting.resourcePathString);
   5795                 }
   5796             }
   5797         }
   5798     }
   5799 
   5800     // Utility method used to move dex files during install.
   5801     private int moveDexFilesLI(PackageParser.Package newPackage) {
   5802         int retCode;
   5803         if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
   5804             retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
   5805             if (retCode != 0) {
   5806                 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
   5807                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5808             }
   5809         }
   5810         return PackageManager.INSTALL_SUCCEEDED;
   5811     }
   5812 
   5813     private void updateSettingsLI(PackageParser.Package newPackage,
   5814             String installerPackageName, PackageInstalledInfo res) {
   5815         String pkgName = newPackage.packageName;
   5816         synchronized (mPackages) {
   5817             //write settings. the installStatus will be incomplete at this stage.
   5818             //note that the new package setting would have already been
   5819             //added to mPackages. It hasn't been persisted yet.
   5820             mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
   5821             mSettings.writeLP();
   5822         }
   5823 
   5824         if ((res.returnCode = moveDexFilesLI(newPackage))
   5825                 != PackageManager.INSTALL_SUCCEEDED) {
   5826             // Discontinue if moving dex files failed.
   5827             return;
   5828         }
   5829         if((res.returnCode = setPermissionsLI(newPackage))
   5830                 != PackageManager.INSTALL_SUCCEEDED) {
   5831             if (mInstaller != null) {
   5832                 mInstaller.rmdex(newPackage.mScanPath);
   5833             }
   5834             return;
   5835         } else {
   5836             Log.d(TAG, "New package installed in " + newPackage.mPath);
   5837         }
   5838         synchronized (mPackages) {
   5839             updatePermissionsLP(newPackage.packageName, newPackage,
   5840                     newPackage.permissions.size() > 0, true, false);
   5841             res.name = pkgName;
   5842             res.uid = newPackage.applicationInfo.uid;
   5843             res.pkg = newPackage;
   5844             mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
   5845             mSettings.setInstallerPackageName(pkgName, installerPackageName);
   5846             res.returnCode = PackageManager.INSTALL_SUCCEEDED;
   5847             //to update install status
   5848             mSettings.writeLP();
   5849         }
   5850     }
   5851 
   5852     private void installPackageLI(InstallArgs args,
   5853             boolean newInstall, PackageInstalledInfo res) {
   5854         int pFlags = args.flags;
   5855         String installerPackageName = args.installerPackageName;
   5856         File tmpPackageFile = new File(args.getCodePath());
   5857         boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
   5858         boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
   5859         boolean replace = false;
   5860         int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
   5861                 | (newInstall ? SCAN_NEW_INSTALL : 0);
   5862         // Result object to be returned
   5863         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
   5864 
   5865         // Retrieve PackageSettings and parse package
   5866         int parseFlags = PackageParser.PARSE_CHATTY |
   5867         (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
   5868         (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
   5869         parseFlags |= mDefParseFlags;
   5870         PackageParser pp = new PackageParser(tmpPackageFile.getPath());
   5871         pp.setSeparateProcesses(mSeparateProcesses);
   5872         final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
   5873                 null, mMetrics, parseFlags);
   5874         if (pkg == null) {
   5875             res.returnCode = pp.getParseError();
   5876             return;
   5877         }
   5878         String pkgName = res.name = pkg.packageName;
   5879         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
   5880             if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
   5881                 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
   5882                 return;
   5883             }
   5884         }
   5885         if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
   5886             res.returnCode = pp.getParseError();
   5887             return;
   5888         }
   5889         // Get rid of all references to package scan path via parser.
   5890         pp = null;
   5891         String oldCodePath = null;
   5892         boolean systemApp = false;
   5893         synchronized (mPackages) {
   5894             // Check if installing already existing package
   5895             if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
   5896                 String oldName = mSettings.mRenamedPackages.get(pkgName);
   5897                 if (pkg.mOriginalPackages != null
   5898                         && pkg.mOriginalPackages.contains(oldName)
   5899                         && mPackages.containsKey(oldName)) {
   5900                     // This package is derived from an original package,
   5901                     // and this device has been updating from that original
   5902                     // name.  We must continue using the original name, so
   5903                     // rename the new package here.
   5904                     pkg.setPackageName(oldName);
   5905                     pkgName = pkg.packageName;
   5906                     replace = true;
   5907                 } else if (mPackages.containsKey(pkgName)) {
   5908                     // This package, under its official name, already exists
   5909                     // on the device; we should replace it.
   5910                     replace = true;
   5911                 }
   5912             }
   5913             PackageSetting ps = mSettings.mPackages.get(pkgName);
   5914             if (ps != null) {
   5915                 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
   5916                 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
   5917                     systemApp = (ps.pkg.applicationInfo.flags &
   5918                             ApplicationInfo.FLAG_SYSTEM) != 0;
   5919                 }
   5920             }
   5921         }
   5922 
   5923         if (systemApp && onSd) {
   5924             // Disable updates to system apps on sdcard
   5925             Slog.w(TAG, "Cannot install updates to system apps on sdcard");
   5926             res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
   5927             return;
   5928         }
   5929 
   5930         if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
   5931             res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5932             return;
   5933         }
   5934         // Set application objects path explicitly after the rename
   5935         setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
   5936         if (replace) {
   5937             replacePackageLI(pkg, parseFlags, scanMode,
   5938                     installerPackageName, res);
   5939         } else {
   5940             installNewPackageLI(pkg, parseFlags, scanMode,
   5941                     installerPackageName,res);
   5942         }
   5943     }
   5944 
   5945     private int setPermissionsLI(PackageParser.Package newPackage) {
   5946         String pkgName = newPackage.packageName;
   5947         int retCode = 0;
   5948         // TODO Gross hack but fix later. Ideally move this to be a post installation
   5949         // check after alloting uid.
   5950         if ((newPackage.applicationInfo.flags
   5951                 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
   5952             File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
   5953             try {
   5954                 extractPublicFiles(newPackage, destResourceFile);
   5955             } catch (IOException e) {
   5956                 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a" +
   5957                            " forward-locked app.");
   5958                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5959             } finally {
   5960                 //TODO clean up the extracted public files
   5961             }
   5962             if (mInstaller != null) {
   5963                 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
   5964                         newPackage.applicationInfo.uid);
   5965             } else {
   5966                 final int filePermissions =
   5967                         FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
   5968                 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
   5969                                                    newPackage.applicationInfo.uid);
   5970             }
   5971         } else {
   5972             // The permissions on the resource file was set when it was copied for
   5973             // non forward locked apps and apps on sdcard
   5974         }
   5975 
   5976         if (retCode != 0) {
   5977             Slog.e(TAG, "Couldn't set new package file permissions for " +
   5978                     newPackage.mPath
   5979                        + ". The return code was: " + retCode);
   5980             // TODO Define new internal error
   5981             return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
   5982         }
   5983         return PackageManager.INSTALL_SUCCEEDED;
   5984     }
   5985 
   5986     private boolean isForwardLocked(PackageParser.Package pkg) {
   5987         return  ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
   5988     }
   5989 
   5990     private boolean isExternal(PackageParser.Package pkg) {
   5991         return  ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
   5992     }
   5993 
   5994     private void extractPublicFiles(PackageParser.Package newPackage,
   5995                                     File publicZipFile) throws IOException {
   5996         final ZipOutputStream publicZipOutStream =
   5997                 new ZipOutputStream(new FileOutputStream(publicZipFile));
   5998         final ZipFile privateZip = new ZipFile(newPackage.mPath);
   5999 
   6000         // Copy manifest, resources.arsc and res directory to public zip
   6001 
   6002         final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
   6003         while (privateZipEntries.hasMoreElements()) {
   6004             final ZipEntry zipEntry = privateZipEntries.nextElement();
   6005             final String zipEntryName = zipEntry.getName();
   6006             if ("AndroidManifest.xml".equals(zipEntryName)
   6007                 || "resources.arsc".equals(zipEntryName)
   6008                 || zipEntryName.startsWith("res/")) {
   6009                 try {
   6010                     copyZipEntry(zipEntry, privateZip, publicZipOutStream);
   6011                 } catch (IOException e) {
   6012                     try {
   6013                         publicZipOutStream.close();
   6014                         throw e;
   6015                     } finally {
   6016                         publicZipFile.delete();
   6017                     }
   6018                 }
   6019             }
   6020         }
   6021 
   6022         publicZipOutStream.close();
   6023         FileUtils.setPermissions(
   6024                 publicZipFile.getAbsolutePath(),
   6025                 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
   6026                 -1, -1);
   6027     }
   6028 
   6029     private static void copyZipEntry(ZipEntry zipEntry,
   6030                                      ZipFile inZipFile,
   6031                                      ZipOutputStream outZipStream) throws IOException {
   6032         byte[] buffer = new byte[4096];
   6033         int num;
   6034 
   6035         ZipEntry newEntry;
   6036         if (zipEntry.getMethod() == ZipEntry.STORED) {
   6037             // Preserve the STORED method of the input entry.
   6038             newEntry = new ZipEntry(zipEntry);
   6039         } else {
   6040             // Create a new entry so that the compressed len is recomputed.
   6041             newEntry = new ZipEntry(zipEntry.getName());
   6042         }
   6043         outZipStream.putNextEntry(newEntry);
   6044 
   6045         InputStream data = inZipFile.getInputStream(zipEntry);
   6046         while ((num = data.read(buffer)) > 0) {
   6047             outZipStream.write(buffer, 0, num);
   6048         }
   6049         outZipStream.flush();
   6050     }
   6051 
   6052     private void deleteTempPackageFiles() {
   6053         FilenameFilter filter = new FilenameFilter() {
   6054             public boolean accept(File dir, String name) {
   6055                 return name.startsWith("vmdl") && name.endsWith(".tmp");
   6056             }
   6057         };
   6058         String tmpFilesList[] = mAppInstallDir.list(filter);
   6059         if(tmpFilesList == null) {
   6060             return;
   6061         }
   6062         for(int i = 0; i < tmpFilesList.length; i++) {
   6063             File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
   6064             tmpFile.delete();
   6065         }
   6066     }
   6067 
   6068     private File createTempPackageFile(File installDir) {
   6069         File tmpPackageFile;
   6070         try {
   6071             tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
   6072         } catch (IOException e) {
   6073             Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
   6074             return null;
   6075         }
   6076         try {
   6077             FileUtils.setPermissions(
   6078                     tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
   6079                     -1, -1);
   6080         } catch (IOException e) {
   6081             Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
   6082             return null;
   6083         }
   6084         return tmpPackageFile;
   6085     }
   6086 
   6087     public void deletePackage(final String packageName,
   6088                               final IPackageDeleteObserver observer,
   6089                               final int flags) {
   6090         mContext.enforceCallingOrSelfPermission(
   6091                 android.Manifest.permission.DELETE_PACKAGES, null);
   6092         // Queue up an async operation since the package deletion may take a little while.
   6093         mHandler.post(new Runnable() {
   6094             public void run() {
   6095                 mHandler.removeCallbacks(this);
   6096                 final boolean succeded = deletePackageX(packageName, true, true, flags);
   6097                 if (observer != null) {
   6098                     try {
   6099                         observer.packageDeleted(succeded);
   6100                     } catch (RemoteException e) {
   6101                         Log.i(TAG, "Observer no longer exists.");
   6102                     } //end catch
   6103                 } //end if
   6104             } //end run
   6105         });
   6106     }
   6107 
   6108     /**
   6109      *  This method is an internal method that could be get invoked either
   6110      *  to delete an installed package or to clean up a failed installation.
   6111      *  After deleting an installed package, a broadcast is sent to notify any
   6112      *  listeners that the package has been installed. For cleaning up a failed
   6113      *  installation, the broadcast is not necessary since the package's
   6114      *  installation wouldn't have sent the initial broadcast either
   6115      *  The key steps in deleting a package are
   6116      *  deleting the package information in internal structures like mPackages,
   6117      *  deleting the packages base directories through installd
   6118      *  updating mSettings to reflect current status
   6119      *  persisting settings for later use
   6120      *  sending a broadcast if necessary
   6121      */
   6122     private boolean deletePackageX(String packageName, boolean sendBroadCast,
   6123                                    boolean deleteCodeAndResources, int flags) {
   6124         PackageRemovedInfo info = new PackageRemovedInfo();
   6125         boolean res;
   6126 
   6127         IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
   6128                 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
   6129         try {
   6130             if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
   6131                 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
   6132                 return false;
   6133             }
   6134         } catch (RemoteException e) {
   6135         }
   6136 
   6137         synchronized (mInstallLock) {
   6138             res = deletePackageLI(packageName, deleteCodeAndResources,
   6139                     flags | REMOVE_CHATTY, info);
   6140         }
   6141 
   6142         if(res && sendBroadCast) {
   6143             boolean systemUpdate = info.isRemovedPackageSystemUpdate;
   6144             info.sendBroadcast(deleteCodeAndResources, systemUpdate);
   6145 
   6146             // If the removed package was a system update, the old system packaged
   6147             // was re-enabled; we need to broadcast this information
   6148             if (systemUpdate) {
   6149                 Bundle extras = new Bundle(1);
   6150                 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
   6151                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
   6152 
   6153                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, null);
   6154                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, null);
   6155             }
   6156         }
   6157         // Force a gc here.
   6158         Runtime.getRuntime().gc();
   6159         // Delete the resources here after sending the broadcast to let
   6160         // other processes clean up before deleting resources.
   6161         if (info.args != null) {
   6162             synchronized (mInstallLock) {
   6163                 info.args.doPostDeleteLI(deleteCodeAndResources);
   6164             }
   6165         }
   6166         return res;
   6167     }
   6168 
   6169     static class PackageRemovedInfo {
   6170         String removedPackage;
   6171         int uid = -1;
   6172         int removedUid = -1;
   6173         boolean isRemovedPackageSystemUpdate = false;
   6174         // Clean up resources deleted packages.
   6175         InstallArgs args = null;
   6176 
   6177         void sendBroadcast(boolean fullRemove, boolean replacing) {
   6178             Bundle extras = new Bundle(1);
   6179             extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
   6180             extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
   6181             if (replacing) {
   6182                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
   6183             }
   6184             if (removedPackage != null) {
   6185                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras, null);
   6186             }
   6187             if (removedUid >= 0) {
   6188                 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null);
   6189             }
   6190         }
   6191     }
   6192 
   6193     /*
   6194      * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
   6195      * flag is not set, the data directory is removed as well.
   6196      * make sure this flag is set for partially installed apps. If not its meaningless to
   6197      * delete a partially installed application.
   6198      */
   6199     private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
   6200             int flags) {
   6201         String packageName = p.packageName;
   6202         if (outInfo != null) {
   6203             outInfo.removedPackage = packageName;
   6204         }
   6205         removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
   6206         // Retrieve object to delete permissions for shared user later on
   6207         PackageSetting deletedPs;
   6208         synchronized (mPackages) {
   6209             deletedPs = mSettings.mPackages.get(packageName);
   6210         }
   6211         if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
   6212             if (mInstaller != null) {
   6213                 int retCode = mInstaller.remove(packageName);
   6214                 if (retCode < 0) {
   6215                     Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
   6216                                + packageName + ", retcode=" + retCode);
   6217                     // we don't consider this to be a failure of the core package deletion
   6218                 }
   6219             } else {
   6220                 //for emulator
   6221                 PackageParser.Package pkg = mPackages.get(packageName);
   6222                 File dataDir = new File(pkg.applicationInfo.dataDir);
   6223                 dataDir.delete();
   6224             }
   6225         }
   6226         synchronized (mPackages) {
   6227             if (deletedPs != null) {
   6228                 schedulePackageCleaning(packageName);
   6229 
   6230                 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
   6231                     if (outInfo != null) {
   6232                         outInfo.removedUid = mSettings.removePackageLP(packageName);
   6233                     }
   6234                     if (deletedPs != null) {
   6235                         updatePermissionsLP(deletedPs.name, null, false, false, false);
   6236                         if (deletedPs.sharedUser != null) {
   6237                             // remove permissions associated with package
   6238                             mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
   6239                         }
   6240                     }
   6241                 }
   6242                 // remove from preferred activities.
   6243                 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
   6244                 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
   6245                     if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
   6246                         removed.add(pa);
   6247                     }
   6248                 }
   6249                 for (PreferredActivity pa : removed) {
   6250                     mSettings.mPreferredActivities.removeFilter(pa);
   6251                 }
   6252             }
   6253             // Save settings now
   6254             mSettings.writeLP();
   6255         }
   6256     }
   6257 
   6258     /*
   6259      * Tries to delete system package.
   6260      */
   6261     private boolean deleteSystemPackageLI(PackageParser.Package p,
   6262             int flags, PackageRemovedInfo outInfo) {
   6263         ApplicationInfo applicationInfo = p.applicationInfo;
   6264         //applicable for non-partially installed applications only
   6265         if (applicationInfo == null) {
   6266             Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
   6267             return false;
   6268         }
   6269         PackageSetting ps = null;
   6270         // Confirm if the system package has been updated
   6271         // An updated system app can be deleted. This will also have to restore
   6272         // the system pkg from system partition
   6273         synchronized (mPackages) {
   6274             ps = mSettings.getDisabledSystemPkg(p.packageName);
   6275         }
   6276         if (ps == null) {
   6277             Slog.w(TAG, "Attempt to delete system package "+ p.packageName);
   6278             return false;
   6279         } else {
   6280             Log.i(TAG, "Deleting system pkg from data partition");
   6281         }
   6282         // Delete the updated package
   6283         outInfo.isRemovedPackageSystemUpdate = true;
   6284         boolean deleteCodeAndResources = false;
   6285         if (ps.versionCode <  p.mVersionCode) {
   6286             // Delete code and resources for downgrades
   6287             deleteCodeAndResources = true;
   6288             if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
   6289                 flags &= ~PackageManager.DONT_DELETE_DATA;
   6290             }
   6291         } else {
   6292             // Preserve data by setting flag
   6293             if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
   6294                 flags |= PackageManager.DONT_DELETE_DATA;
   6295             }
   6296         }
   6297         boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
   6298         if (!ret) {
   6299             return false;
   6300         }
   6301         synchronized (mPackages) {
   6302             // Reinstate the old system package
   6303             mSettings.enableSystemPackageLP(p.packageName);
   6304             // Remove any native libraries.
   6305             removeNativeBinariesLI(p);
   6306         }
   6307         // Install the system package
   6308         PackageParser.Package newPkg = scanPackageLI(ps.codePath,
   6309                 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
   6310                 SCAN_MONITOR | SCAN_NO_PATHS);
   6311 
   6312         if (newPkg == null) {
   6313             Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
   6314             return false;
   6315         }
   6316         synchronized (mPackages) {
   6317             updatePermissionsLP(newPkg.packageName, newPkg, true, true, false);
   6318             mSettings.writeLP();
   6319         }
   6320         return true;
   6321     }
   6322 
   6323     private boolean deleteInstalledPackageLI(PackageParser.Package p,
   6324             boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
   6325         ApplicationInfo applicationInfo = p.applicationInfo;
   6326         if (applicationInfo == null) {
   6327             Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
   6328             return false;
   6329         }
   6330         if (outInfo != null) {
   6331             outInfo.uid = applicationInfo.uid;
   6332         }
   6333 
   6334         // Delete package data from internal structures and also remove data if flag is set
   6335         removePackageDataLI(p, outInfo, flags);
   6336 
   6337         // Delete application code and resources
   6338         if (deleteCodeAndResources) {
   6339             // TODO can pick up from PackageSettings as well
   6340             int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0) ?
   6341                     PackageManager.INSTALL_EXTERNAL : 0;
   6342             installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
   6343                     PackageManager.INSTALL_FORWARD_LOCK : 0;
   6344             outInfo.args = createInstallArgs(installFlags,
   6345                     applicationInfo.sourceDir, applicationInfo.publicSourceDir);
   6346         }
   6347         return true;
   6348     }
   6349 
   6350     /*
   6351      * This method handles package deletion in general
   6352      */
   6353     private boolean deletePackageLI(String packageName,
   6354             boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
   6355         if (packageName == null) {
   6356             Slog.w(TAG, "Attempt to delete null packageName.");
   6357             return false;
   6358         }
   6359         PackageParser.Package p;
   6360         boolean dataOnly = false;
   6361         synchronized (mPackages) {
   6362             p = mPackages.get(packageName);
   6363             if (p == null) {
   6364                 //this retrieves partially installed apps
   6365                 dataOnly = true;
   6366                 PackageSetting ps = mSettings.mPackages.get(packageName);
   6367                 if (ps == null) {
   6368                     Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
   6369                     return false;
   6370                 }
   6371                 p = ps.pkg;
   6372             }
   6373         }
   6374         if (p == null) {
   6375             Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
   6376             return false;
   6377         }
   6378 
   6379         if (dataOnly) {
   6380             // Delete application data first
   6381             removePackageDataLI(p, outInfo, flags);
   6382             return true;
   6383         }
   6384         // At this point the package should have ApplicationInfo associated with it
   6385         if (p.applicationInfo == null) {
   6386             Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
   6387             return false;
   6388         }
   6389         boolean ret = false;
   6390         if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
   6391             Log.i(TAG, "Removing system package:"+p.packageName);
   6392             // When an updated system application is deleted we delete the existing resources as well and
   6393             // fall back to existing code in system partition
   6394             ret = deleteSystemPackageLI(p, flags, outInfo);
   6395         } else {
   6396             Log.i(TAG, "Removing non-system package:"+p.packageName);
   6397             // Kill application pre-emptively especially for apps on sd.
   6398             killApplication(packageName, p.applicationInfo.uid);
   6399             ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
   6400         }
   6401         return ret;
   6402     }
   6403 
   6404     public void clearApplicationUserData(final String packageName,
   6405             final IPackageDataObserver observer) {
   6406         mContext.enforceCallingOrSelfPermission(
   6407                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
   6408         // Queue up an async operation since the package deletion may take a little while.
   6409         mHandler.post(new Runnable() {
   6410             public void run() {
   6411                 mHandler.removeCallbacks(this);
   6412                 final boolean succeeded;
   6413                 synchronized (mInstallLock) {
   6414                     succeeded = clearApplicationUserDataLI(packageName);
   6415                 }
   6416                 if (succeeded) {
   6417                     // invoke DeviceStorageMonitor's update method to clear any notifications
   6418                     DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
   6419                             ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
   6420                     if (dsm != null) {
   6421                         dsm.updateMemory();
   6422                     }
   6423                 }
   6424                 if(observer != null) {
   6425                     try {
   6426                         observer.onRemoveCompleted(packageName, succeeded);
   6427                     } catch (RemoteException e) {
   6428                         Log.i(TAG, "Observer no longer exists.");
   6429                     }
   6430                 } //end if observer
   6431             } //end run
   6432         });
   6433     }
   6434 
   6435     private boolean clearApplicationUserDataLI(String packageName) {
   6436         if (packageName == null) {
   6437             Slog.w(TAG, "Attempt to delete null packageName.");
   6438             return false;
   6439         }
   6440         PackageParser.Package p;
   6441         boolean dataOnly = false;
   6442         synchronized (mPackages) {
   6443             p = mPackages.get(packageName);
   6444             if(p == null) {
   6445                 dataOnly = true;
   6446                 PackageSetting ps = mSettings.mPackages.get(packageName);
   6447                 if((ps == null) || (ps.pkg == null)) {
   6448                     Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
   6449                     return false;
   6450                 }
   6451                 p = ps.pkg;
   6452             }
   6453         }
   6454 
   6455         if(!dataOnly) {
   6456             //need to check this only for fully installed applications
   6457             if (p == null) {
   6458                 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
   6459                 return false;
   6460             }
   6461             final ApplicationInfo applicationInfo = p.applicationInfo;
   6462             if (applicationInfo == null) {
   6463                 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
   6464                 return false;
   6465             }
   6466         }
   6467         if (mInstaller != null) {
   6468             int retCode = mInstaller.clearUserData(packageName);
   6469             if (retCode < 0) {
   6470                 Slog.w(TAG, "Couldn't remove cache files for package: "
   6471                         + packageName);
   6472                 return false;
   6473             }
   6474         }
   6475         return true;
   6476     }
   6477 
   6478     public void deleteApplicationCacheFiles(final String packageName,
   6479             final IPackageDataObserver observer) {
   6480         mContext.enforceCallingOrSelfPermission(
   6481                 android.Manifest.permission.DELETE_CACHE_FILES, null);
   6482         // Queue up an async operation since the package deletion may take a little while.
   6483         mHandler.post(new Runnable() {
   6484             public void run() {
   6485                 mHandler.removeCallbacks(this);
   6486                 final boolean succeded;
   6487                 synchronized (mInstallLock) {
   6488                     succeded = deleteApplicationCacheFilesLI(packageName);
   6489                 }
   6490                 if(observer != null) {
   6491                     try {
   6492                         observer.onRemoveCompleted(packageName, succeded);
   6493                     } catch (RemoteException e) {
   6494                         Log.i(TAG, "Observer no longer exists.");
   6495                     }
   6496                 } //end if observer
   6497             } //end run
   6498         });
   6499     }
   6500 
   6501     private boolean deleteApplicationCacheFilesLI(String packageName) {
   6502         if (packageName == null) {
   6503             Slog.w(TAG, "Attempt to delete null packageName.");
   6504             return false;
   6505         }
   6506         PackageParser.Package p;
   6507         synchronized (mPackages) {
   6508             p = mPackages.get(packageName);
   6509         }
   6510         if (p == null) {
   6511             Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
   6512             return false;
   6513         }
   6514         final ApplicationInfo applicationInfo = p.applicationInfo;
   6515         if (applicationInfo == null) {
   6516             Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
   6517             return false;
   6518         }
   6519         if (mInstaller != null) {
   6520             int retCode = mInstaller.deleteCacheFiles(packageName);
   6521             if (retCode < 0) {
   6522                 Slog.w(TAG, "Couldn't remove cache files for package: "
   6523                            + packageName);
   6524                 return false;
   6525             }
   6526         }
   6527         return true;
   6528     }
   6529 
   6530     public void getPackageSizeInfo(final String packageName,
   6531             final IPackageStatsObserver observer) {
   6532         mContext.enforceCallingOrSelfPermission(
   6533                 android.Manifest.permission.GET_PACKAGE_SIZE, null);
   6534         // Queue up an async operation since the package deletion may take a little while.
   6535         mHandler.post(new Runnable() {
   6536             public void run() {
   6537                 mHandler.removeCallbacks(this);
   6538                 PackageStats lStats = new PackageStats(packageName);
   6539                 final boolean succeded;
   6540                 synchronized (mInstallLock) {
   6541                     succeded = getPackageSizeInfoLI(packageName, lStats);
   6542                 }
   6543                 if(observer != null) {
   6544                     try {
   6545                         observer.onGetStatsCompleted(lStats, succeded);
   6546                     } catch (RemoteException e) {
   6547                         Log.i(TAG, "Observer no longer exists.");
   6548                     }
   6549                 } //end if observer
   6550             } //end run
   6551         });
   6552     }
   6553 
   6554     private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
   6555         if (packageName == null) {
   6556             Slog.w(TAG, "Attempt to get size of null packageName.");
   6557             return false;
   6558         }
   6559         PackageParser.Package p;
   6560         boolean dataOnly = false;
   6561         synchronized (mPackages) {
   6562             p = mPackages.get(packageName);
   6563             if(p == null) {
   6564                 dataOnly = true;
   6565                 PackageSetting ps = mSettings.mPackages.get(packageName);
   6566                 if((ps == null) || (ps.pkg == null)) {
   6567                     Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
   6568                     return false;
   6569                 }
   6570                 p = ps.pkg;
   6571             }
   6572         }
   6573         String publicSrcDir = null;
   6574         if(!dataOnly) {
   6575             final ApplicationInfo applicationInfo = p.applicationInfo;
   6576             if (applicationInfo == null) {
   6577                 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
   6578                 return false;
   6579             }
   6580             publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
   6581         }
   6582         if (mInstaller != null) {
   6583             int res = mInstaller.getSizeInfo(packageName, p.mPath,
   6584                     publicSrcDir, pStats);
   6585             if (res < 0) {
   6586                 return false;
   6587             } else {
   6588                 return true;
   6589             }
   6590         }
   6591         return true;
   6592     }
   6593 
   6594 
   6595     public void addPackageToPreferred(String packageName) {
   6596         Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
   6597     }
   6598 
   6599     public void removePackageFromPreferred(String packageName) {
   6600         Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
   6601     }
   6602 
   6603     public List<PackageInfo> getPreferredPackages(int flags) {
   6604         return new ArrayList<PackageInfo>();
   6605     }
   6606 
   6607     int getUidTargetSdkVersionLockedLP(int uid) {
   6608         Object obj = mSettings.getUserIdLP(uid);
   6609         if (obj instanceof SharedUserSetting) {
   6610             SharedUserSetting sus = (SharedUserSetting)obj;
   6611             final int N = sus.packages.size();
   6612             int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
   6613             Iterator<PackageSetting> it = sus.packages.iterator();
   6614             int i=0;
   6615             while (it.hasNext()) {
   6616                 PackageSetting ps = it.next();
   6617                 if (ps.pkg != null) {
   6618                     int v = ps.pkg.applicationInfo.targetSdkVersion;
   6619                     if (v < vers) vers = v;
   6620                 }
   6621             }
   6622             return vers;
   6623         } else if (obj instanceof PackageSetting) {
   6624             PackageSetting ps = (PackageSetting)obj;
   6625             if (ps.pkg != null) {
   6626                 return ps.pkg.applicationInfo.targetSdkVersion;
   6627             }
   6628         }
   6629         return Build.VERSION_CODES.CUR_DEVELOPMENT;
   6630     }
   6631 
   6632     public void addPreferredActivity(IntentFilter filter, int match,
   6633             ComponentName[] set, ComponentName activity) {
   6634         synchronized (mPackages) {
   6635             if (mContext.checkCallingOrSelfPermission(
   6636                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
   6637                     != PackageManager.PERMISSION_GRANTED) {
   6638                 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
   6639                         < Build.VERSION_CODES.FROYO) {
   6640                     Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
   6641                             + Binder.getCallingUid());
   6642                     return;
   6643                 }
   6644                 mContext.enforceCallingOrSelfPermission(
   6645                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
   6646             }
   6647 
   6648             Slog.i(TAG, "Adding preferred activity " + activity + ":");
   6649             filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
   6650             mSettings.mPreferredActivities.addFilter(
   6651                     new PreferredActivity(filter, match, set, activity));
   6652             scheduleWriteSettingsLocked();
   6653         }
   6654     }
   6655 
   6656     public void replacePreferredActivity(IntentFilter filter, int match,
   6657             ComponentName[] set, ComponentName activity) {
   6658         if (filter.countActions() != 1) {
   6659             throw new IllegalArgumentException(
   6660                     "replacePreferredActivity expects filter to have only 1 action.");
   6661         }
   6662         if (filter.countCategories() != 1) {
   6663             throw new IllegalArgumentException(
   6664                     "replacePreferredActivity expects filter to have only 1 category.");
   6665         }
   6666         if (filter.countDataAuthorities() != 0
   6667                 || filter.countDataPaths() != 0
   6668                 || filter.countDataSchemes() != 0
   6669                 || filter.countDataTypes() != 0) {
   6670             throw new IllegalArgumentException(
   6671                     "replacePreferredActivity expects filter to have no data authorities, " +
   6672                     "paths, schemes or types.");
   6673         }
   6674         synchronized (mPackages) {
   6675             if (mContext.checkCallingOrSelfPermission(
   6676                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
   6677                     != PackageManager.PERMISSION_GRANTED) {
   6678                 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
   6679                         < Build.VERSION_CODES.FROYO) {
   6680                     Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
   6681                             + Binder.getCallingUid());
   6682                     return;
   6683                 }
   6684                 mContext.enforceCallingOrSelfPermission(
   6685                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
   6686             }
   6687 
   6688             Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
   6689             String action = filter.getAction(0);
   6690             String category = filter.getCategory(0);
   6691             while (it.hasNext()) {
   6692                 PreferredActivity pa = it.next();
   6693                 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
   6694                     it.remove();
   6695                     Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
   6696                     filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
   6697                 }
   6698             }
   6699             addPreferredActivity(filter, match, set, activity);
   6700         }
   6701     }
   6702 
   6703     public void clearPackagePreferredActivities(String packageName) {
   6704         synchronized (mPackages) {
   6705             int uid = Binder.getCallingUid();
   6706             PackageParser.Package pkg = mPackages.get(packageName);
   6707             if (pkg == null || pkg.applicationInfo.uid != uid) {
   6708                 if (mContext.checkCallingOrSelfPermission(
   6709                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
   6710                         != PackageManager.PERMISSION_GRANTED) {
   6711                     if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
   6712                             < Build.VERSION_CODES.FROYO) {
   6713                         Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
   6714                                 + Binder.getCallingUid());
   6715                         return;
   6716                     }
   6717                     mContext.enforceCallingOrSelfPermission(
   6718                             android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
   6719                 }
   6720             }
   6721 
   6722             if (clearPackagePreferredActivitiesLP(packageName)) {
   6723                 scheduleWriteSettingsLocked();
   6724             }
   6725         }
   6726     }
   6727 
   6728     boolean clearPackagePreferredActivitiesLP(String packageName) {
   6729         boolean changed = false;
   6730         Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
   6731         while (it.hasNext()) {
   6732             PreferredActivity pa = it.next();
   6733             if (pa.mActivity.getPackageName().equals(packageName)) {
   6734                 it.remove();
   6735                 changed = true;
   6736             }
   6737         }
   6738         return changed;
   6739     }
   6740 
   6741     public int getPreferredActivities(List<IntentFilter> outFilters,
   6742             List<ComponentName> outActivities, String packageName) {
   6743 
   6744         int num = 0;
   6745         synchronized (mPackages) {
   6746             Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
   6747             while (it.hasNext()) {
   6748                 PreferredActivity pa = it.next();
   6749                 if (packageName == null
   6750                         || pa.mActivity.getPackageName().equals(packageName)) {
   6751                     if (outFilters != null) {
   6752                         outFilters.add(new IntentFilter(pa));
   6753                     }
   6754                     if (outActivities != null) {
   6755                         outActivities.add(pa.mActivity);
   6756                     }
   6757                 }
   6758             }
   6759         }
   6760 
   6761         return num;
   6762     }
   6763 
   6764     public void setApplicationEnabledSetting(String appPackageName,
   6765             int newState, int flags) {
   6766         setEnabledSetting(appPackageName, null, newState, flags);
   6767     }
   6768 
   6769     public void setComponentEnabledSetting(ComponentName componentName,
   6770             int newState, int flags) {
   6771         setEnabledSetting(componentName.getPackageName(),
   6772                 componentName.getClassName(), newState, flags);
   6773     }
   6774 
   6775     private void setEnabledSetting(
   6776             final String packageName, String className, int newState, final int flags) {
   6777         if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
   6778               || newState == COMPONENT_ENABLED_STATE_ENABLED
   6779               || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
   6780             throw new IllegalArgumentException("Invalid new component state: "
   6781                     + newState);
   6782         }
   6783         PackageSetting pkgSetting;
   6784         final int uid = Binder.getCallingUid();
   6785         final int permission = mContext.checkCallingPermission(
   6786                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
   6787         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
   6788         boolean sendNow = false;
   6789         boolean isApp = (className == null);
   6790         String componentName = isApp ? packageName : className;
   6791         int packageUid = -1;
   6792         ArrayList<String> components;
   6793         synchronized (mPackages) {
   6794             pkgSetting = mSettings.mPackages.get(packageName);
   6795             if (pkgSetting == null) {
   6796                 if (className == null) {
   6797                     throw new IllegalArgumentException(
   6798                             "Unknown package: " + packageName);
   6799                 }
   6800                 throw new IllegalArgumentException(
   6801                         "Unknown component: " + packageName
   6802                         + "/" + className);
   6803             }
   6804             if (!allowedByPermission && (uid != pkgSetting.userId)) {
   6805                 throw new SecurityException(
   6806                         "Permission Denial: attempt to change component state from pid="
   6807                         + Binder.getCallingPid()
   6808                         + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
   6809             }
   6810             if (className == null) {
   6811                 // We're dealing with an application/package level state change
   6812                 if (pkgSetting.enabled == newState) {
   6813                     // Nothing to do
   6814                     return;
   6815                 }
   6816                 pkgSetting.enabled = newState;
   6817             } else {
   6818                 // We're dealing with a component level state change
   6819                 switch (newState) {
   6820                 case COMPONENT_ENABLED_STATE_ENABLED:
   6821                     if (!pkgSetting.enableComponentLP(className)) {
   6822                         return;
   6823                     }
   6824                     break;
   6825                 case COMPONENT_ENABLED_STATE_DISABLED:
   6826                     if (!pkgSetting.disableComponentLP(className)) {
   6827                         return;
   6828                     }
   6829                     break;
   6830                 case COMPONENT_ENABLED_STATE_DEFAULT:
   6831                     if (!pkgSetting.restoreComponentLP(className)) {
   6832                         return;
   6833                     }
   6834                     break;
   6835                 default:
   6836                     Slog.e(TAG, "Invalid new component state: " + newState);
   6837                     return;
   6838                 }
   6839             }
   6840             mSettings.writeLP();
   6841             packageUid = pkgSetting.userId;
   6842             components = mPendingBroadcasts.get(packageName);
   6843             boolean newPackage = components == null;
   6844             if (newPackage) {
   6845                 components = new ArrayList<String>();
   6846             }
   6847             if (!components.contains(componentName)) {
   6848                 components.add(componentName);
   6849             }
   6850             if ((flags&PackageManager.DONT_KILL_APP) == 0) {
   6851                 sendNow = true;
   6852                 // Purge entry from pending broadcast list if another one exists already
   6853                 // since we are sending one right away.
   6854                 mPendingBroadcasts.remove(packageName);
   6855             } else {
   6856                 if (newPackage) {
   6857                     mPendingBroadcasts.put(packageName, components);
   6858                 }
   6859                 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
   6860                     // Schedule a message
   6861                     mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
   6862                 }
   6863             }
   6864         }
   6865 
   6866         long callingId = Binder.clearCallingIdentity();
   6867         try {
   6868             if (sendNow) {
   6869                 sendPackageChangedBroadcast(packageName,
   6870                         (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
   6871             }
   6872         } finally {
   6873             Binder.restoreCallingIdentity(callingId);
   6874         }
   6875     }
   6876 
   6877     private void sendPackageChangedBroadcast(String packageName,
   6878             boolean killFlag, ArrayList<String> componentNames, int packageUid) {
   6879         if (false) Log.v(TAG, "Sending package changed: package=" + packageName
   6880                 + " components=" + componentNames);
   6881         Bundle extras = new Bundle(4);
   6882         extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
   6883         String nameList[] = new String[componentNames.size()];
   6884         componentNames.toArray(nameList);
   6885         extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
   6886         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
   6887         extras.putInt(Intent.EXTRA_UID, packageUid);
   6888         sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED,  packageName, extras, null);
   6889     }
   6890 
   6891     public String getInstallerPackageName(String packageName) {
   6892         synchronized (mPackages) {
   6893             PackageSetting pkg = mSettings.mPackages.get(packageName);
   6894             if (pkg == null) {
   6895                 throw new IllegalArgumentException("Unknown package: " + packageName);
   6896             }
   6897             return pkg.installerPackageName;
   6898         }
   6899     }
   6900 
   6901     public int getApplicationEnabledSetting(String appPackageName) {
   6902         synchronized (mPackages) {
   6903             PackageSetting pkg = mSettings.mPackages.get(appPackageName);
   6904             if (pkg == null) {
   6905                 throw new IllegalArgumentException("Unknown package: " + appPackageName);
   6906             }
   6907             return pkg.enabled;
   6908         }
   6909     }
   6910 
   6911     public int getComponentEnabledSetting(ComponentName componentName) {
   6912         synchronized (mPackages) {
   6913             final String packageNameStr = componentName.getPackageName();
   6914             PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
   6915             if (pkg == null) {
   6916                 throw new IllegalArgumentException("Unknown component: " + componentName);
   6917             }
   6918             final String classNameStr = componentName.getClassName();
   6919             return pkg.currentEnabledStateLP(classNameStr);
   6920         }
   6921     }
   6922 
   6923     public void enterSafeMode() {
   6924         if (!mSystemReady) {
   6925             mSafeMode = true;
   6926         }
   6927     }
   6928 
   6929     public void systemReady() {
   6930         mSystemReady = true;
   6931 
   6932         // Read the compatibilty setting when the system is ready.
   6933         boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
   6934                 mContext.getContentResolver(),
   6935                 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
   6936         PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
   6937         if (DEBUG_SETTINGS) {
   6938             Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
   6939         }
   6940     }
   6941 
   6942     public boolean isSafeMode() {
   6943         return mSafeMode;
   6944     }
   6945 
   6946     public boolean hasSystemUidErrors() {
   6947         return mHasSystemUidErrors;
   6948     }
   6949 
   6950     static String arrayToString(int[] array) {
   6951         StringBuffer buf = new StringBuffer(128);
   6952         buf.append('[');
   6953         if (array != null) {
   6954             for (int i=0; i<array.length; i++) {
   6955                 if (i > 0) buf.append(", ");
   6956                 buf.append(array[i]);
   6957             }
   6958         }
   6959         buf.append(']');
   6960         return buf.toString();
   6961     }
   6962 
   6963     @Override
   6964     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   6965         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
   6966                 != PackageManager.PERMISSION_GRANTED) {
   6967             pw.println("Permission Denial: can't dump ActivityManager from from pid="
   6968                     + Binder.getCallingPid()
   6969                     + ", uid=" + Binder.getCallingUid()
   6970                     + " without permission "
   6971                     + android.Manifest.permission.DUMP);
   6972             return;
   6973         }
   6974 
   6975         String packageName = null;
   6976 
   6977         int opti = 0;
   6978         while (opti < args.length) {
   6979             String opt = args[opti];
   6980             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
   6981                 break;
   6982             }
   6983             opti++;
   6984             if ("-a".equals(opt)) {
   6985                 // Right now we only know how to print all.
   6986             } else if ("-h".equals(opt)) {
   6987                 pw.println("Package manager dump options:");
   6988                 pw.println("  [-h] [cmd] ...");
   6989                 pw.println("  cmd may be one of:");
   6990                 pw.println("    [package.name]: info about given package");
   6991                 return;
   6992             } else {
   6993                 pw.println("Unknown argument: " + opt + "; use -h for help");
   6994             }
   6995         }
   6996 
   6997         // Is the caller requesting to dump a particular piece of data?
   6998         if (opti < args.length) {
   6999             String cmd = args[opti];
   7000             opti++;
   7001             // Is this a package name?
   7002             if ("android".equals(cmd) || cmd.contains(".")) {
   7003                 packageName = cmd;
   7004             }
   7005         }
   7006 
   7007         boolean printedTitle = false;
   7008 
   7009         synchronized (mPackages) {
   7010             if (mActivities.dump(pw, "Activity Resolver Table:", "  ", packageName)) {
   7011                 printedTitle = true;
   7012             }
   7013             if (mReceivers.dump(pw, printedTitle
   7014                     ? "\nReceiver Resolver Table:" : "Receiver Resolver Table:",
   7015                     "  ", packageName)) {
   7016                 printedTitle = true;
   7017             }
   7018             if (mServices.dump(pw, printedTitle
   7019                     ? "\nService Resolver Table:" : "Service Resolver Table:",
   7020                     "  ", packageName)) {
   7021                 printedTitle = true;
   7022             }
   7023             if (mSettings.mPreferredActivities.dump(pw, printedTitle
   7024                     ? "\nPreferred Activities:" : "Preferred Activities:",
   7025                     "  ", packageName)) {
   7026                 printedTitle = true;
   7027             }
   7028             boolean printedSomething = false;
   7029             {
   7030                 for (BasePermission p : mSettings.mPermissions.values()) {
   7031                     if (packageName != null && !packageName.equals(p.sourcePackage)) {
   7032                         continue;
   7033                     }
   7034                     if (!printedSomething) {
   7035                         if (printedTitle) pw.println(" ");
   7036                         pw.println("Permissions:");
   7037                         printedSomething = true;
   7038                         printedTitle = true;
   7039                     }
   7040                     pw.print("  Permission ["); pw.print(p.name); pw.print("] (");
   7041                             pw.print(Integer.toHexString(System.identityHashCode(p)));
   7042                             pw.println("):");
   7043                     pw.print("    sourcePackage="); pw.println(p.sourcePackage);
   7044                     pw.print("    uid="); pw.print(p.uid);
   7045                             pw.print(" gids="); pw.print(arrayToString(p.gids));
   7046                             pw.print(" type="); pw.print(p.type);
   7047                             pw.print(" prot="); pw.println(p.protectionLevel);
   7048                     if (p.packageSetting != null) {
   7049                         pw.print("    packageSetting="); pw.println(p.packageSetting);
   7050                     }
   7051                     if (p.perm != null) {
   7052                         pw.print("    perm="); pw.println(p.perm);
   7053                     }
   7054                 }
   7055             }
   7056             printedSomething = false;
   7057             SharedUserSetting packageSharedUser = null;
   7058             {
   7059                 for (PackageSetting ps : mSettings.mPackages.values()) {
   7060                     if (packageName != null && !packageName.equals(ps.realName)
   7061                             && !packageName.equals(ps.name)) {
   7062                         continue;
   7063                     }
   7064                     if (!printedSomething) {
   7065                         if (printedTitle) pw.println(" ");
   7066                         pw.println("Packages:");
   7067                         printedSomething = true;
   7068                         printedTitle = true;
   7069                     }
   7070                     packageSharedUser = ps.sharedUser;
   7071                     pw.print("  Package [");
   7072                             pw.print(ps.realName != null ? ps.realName : ps.name);
   7073                             pw.print("] (");
   7074                             pw.print(Integer.toHexString(System.identityHashCode(ps)));
   7075                             pw.println("):");
   7076                     if (ps.realName != null) {
   7077                         pw.print("    compat name="); pw.println(ps.name);
   7078                     }
   7079                     pw.print("    userId="); pw.print(ps.userId);
   7080                             pw.print(" gids="); pw.println(arrayToString(ps.gids));
   7081                     pw.print("    sharedUser="); pw.println(ps.sharedUser);
   7082                     pw.print("    pkg="); pw.println(ps.pkg);
   7083                     pw.print("    codePath="); pw.println(ps.codePathString);
   7084                     pw.print("    resourcePath="); pw.println(ps.resourcePathString);
   7085                     if (ps.pkg != null) {
   7086                         pw.print("    dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
   7087                         pw.print("    targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
   7088                         pw.print("    supportsScreens=[");
   7089                         boolean first = true;
   7090                         if ((ps.pkg.applicationInfo.flags &
   7091                                 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
   7092                             if (!first) pw.print(", ");
   7093                             first = false;
   7094                             pw.print("medium");
   7095                         }
   7096                         if ((ps.pkg.applicationInfo.flags &
   7097                                 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
   7098                             if (!first) pw.print(", ");
   7099                             first = false;
   7100                             pw.print("large");
   7101                         }
   7102                         if ((ps.pkg.applicationInfo.flags &
   7103                                 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
   7104                             if (!first) pw.print(", ");
   7105                             first = false;
   7106                             pw.print("small");
   7107                         }
   7108                         if ((ps.pkg.applicationInfo.flags &
   7109                                 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
   7110                             if (!first) pw.print(", ");
   7111                             first = false;
   7112                             pw.print("resizeable");
   7113                         }
   7114                         if ((ps.pkg.applicationInfo.flags &
   7115                                 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
   7116                             if (!first) pw.print(", ");
   7117                             first = false;
   7118                             pw.print("anyDensity");
   7119                         }
   7120                     }
   7121                     pw.println("]");
   7122                     pw.print("    timeStamp="); pw.println(ps.getTimeStampStr());
   7123                     pw.print("    signatures="); pw.println(ps.signatures);
   7124                     pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
   7125                             pw.print(" haveGids="); pw.println(ps.haveGids);
   7126                     pw.print("    pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
   7127                             pw.print(" installStatus="); pw.print(ps.installStatus);
   7128                             pw.print(" enabled="); pw.println(ps.enabled);
   7129                     if (ps.disabledComponents.size() > 0) {
   7130                         pw.println("    disabledComponents:");
   7131                         for (String s : ps.disabledComponents) {
   7132                             pw.print("      "); pw.println(s);
   7133                         }
   7134                     }
   7135                     if (ps.enabledComponents.size() > 0) {
   7136                         pw.println("    enabledComponents:");
   7137                         for (String s : ps.enabledComponents) {
   7138                             pw.print("      "); pw.println(s);
   7139                         }
   7140                     }
   7141                     if (ps.grantedPermissions.size() > 0) {
   7142                         pw.println("    grantedPermissions:");
   7143                         for (String s : ps.grantedPermissions) {
   7144                             pw.print("      "); pw.println(s);
   7145                         }
   7146                     }
   7147                 }
   7148             }
   7149             printedSomething = false;
   7150             if (mSettings.mRenamedPackages.size() > 0) {
   7151                 for (HashMap.Entry<String, String> e
   7152                         : mSettings.mRenamedPackages.entrySet()) {
   7153                     if (packageName != null && !packageName.equals(e.getKey())
   7154                             && !packageName.equals(e.getValue())) {
   7155                         continue;
   7156                     }
   7157                     if (!printedSomething) {
   7158                         if (printedTitle) pw.println(" ");
   7159                         pw.println("Renamed packages:");
   7160                         printedSomething = true;
   7161                         printedTitle = true;
   7162                     }
   7163                     pw.print("  "); pw.print(e.getKey()); pw.print(" -> ");
   7164                             pw.println(e.getValue());
   7165                 }
   7166             }
   7167             printedSomething = false;
   7168             if (mSettings.mDisabledSysPackages.size() > 0) {
   7169                 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
   7170                     if (packageName != null && !packageName.equals(ps.realName)
   7171                             && !packageName.equals(ps.name)) {
   7172                         continue;
   7173                     }
   7174                     if (!printedSomething) {
   7175                         if (printedTitle) pw.println(" ");
   7176                         pw.println("Hidden system packages:");
   7177                         printedSomething = true;
   7178                         printedTitle = true;
   7179                     }
   7180                    pw.print("  Package [");
   7181                             pw.print(ps.realName != null ? ps.realName : ps.name);
   7182                             pw.print("] (");
   7183                             pw.print(Integer.toHexString(System.identityHashCode(ps)));
   7184                             pw.println("):");
   7185                     if (ps.realName != null) {
   7186                         pw.print("    compat name="); pw.println(ps.name);
   7187                     }
   7188                     pw.print("    userId="); pw.println(ps.userId);
   7189                     pw.print("    sharedUser="); pw.println(ps.sharedUser);
   7190                     pw.print("    codePath="); pw.println(ps.codePathString);
   7191                     pw.print("    resourcePath="); pw.println(ps.resourcePathString);
   7192                 }
   7193             }
   7194             printedSomething = false;
   7195             {
   7196                 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
   7197                     if (packageName != null && su != packageSharedUser) {
   7198                         continue;
   7199                     }
   7200                     if (!printedSomething) {
   7201                         if (printedTitle) pw.println(" ");
   7202                         pw.println("Shared users:");
   7203                         printedSomething = true;
   7204                         printedTitle = true;
   7205                     }
   7206                     pw.print("  SharedUser ["); pw.print(su.name); pw.print("] (");
   7207                             pw.print(Integer.toHexString(System.identityHashCode(su)));
   7208                             pw.println("):");
   7209                     pw.print("    userId="); pw.print(su.userId);
   7210                             pw.print(" gids="); pw.println(arrayToString(su.gids));
   7211                     pw.println("    grantedPermissions:");
   7212                     for (String s : su.grantedPermissions) {
   7213                         pw.print("      "); pw.println(s);
   7214                     }
   7215                 }
   7216             }
   7217 
   7218             if (packageName == null) {
   7219                 if (printedTitle) pw.println(" ");
   7220                 printedTitle = true;
   7221                 pw.println("Settings parse messages:");
   7222                 pw.println(mSettings.mReadMessages.toString());
   7223 
   7224                 pw.println(" ");
   7225                 pw.println("Package warning messages:");
   7226                 File fname = getSettingsProblemFile();
   7227                 FileInputStream in;
   7228                 try {
   7229                     in = new FileInputStream(fname);
   7230                     int avail = in.available();
   7231                     byte[] data = new byte[avail];
   7232                     in.read(data);
   7233                     pw.println(new String(data));
   7234                 } catch (FileNotFoundException e) {
   7235                 } catch (IOException e) {
   7236                 }
   7237             }
   7238         }
   7239 
   7240         synchronized (mProviders) {
   7241             boolean printedSomething = false;
   7242             for (PackageParser.Provider p : mProviders.values()) {
   7243                 if (packageName != null && !packageName.equals(p.info.packageName)) {
   7244                     continue;
   7245                 }
   7246                 if (!printedSomething) {
   7247                     if (printedTitle) pw.println(" ");
   7248                     pw.println("Registered ContentProviders:");
   7249                     printedSomething = true;
   7250                     printedTitle = true;
   7251                 }
   7252                 pw.print("  ["); pw.print(p.info.authority); pw.print("]: ");
   7253                         pw.println(p.toString());
   7254             }
   7255         }
   7256     }
   7257 
   7258     static final class BasePermission {
   7259         final static int TYPE_NORMAL = 0;
   7260         final static int TYPE_BUILTIN = 1;
   7261         final static int TYPE_DYNAMIC = 2;
   7262 
   7263         final String name;
   7264         String sourcePackage;
   7265         PackageSettingBase packageSetting;
   7266         final int type;
   7267         int protectionLevel;
   7268         PackageParser.Permission perm;
   7269         PermissionInfo pendingInfo;
   7270         int uid;
   7271         int[] gids;
   7272 
   7273         BasePermission(String _name, String _sourcePackage, int _type) {
   7274             name = _name;
   7275             sourcePackage = _sourcePackage;
   7276             type = _type;
   7277             // Default to most conservative protection level.
   7278             protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
   7279         }
   7280 
   7281         public String toString() {
   7282             return "BasePermission{"
   7283                 + Integer.toHexString(System.identityHashCode(this))
   7284                 + " " + name + "}";
   7285         }
   7286     }
   7287 
   7288     static class PackageSignatures {
   7289         private Signature[] mSignatures;
   7290 
   7291         PackageSignatures(Signature[] sigs) {
   7292             assignSignatures(sigs);
   7293         }
   7294 
   7295         PackageSignatures() {
   7296         }
   7297 
   7298         void writeXml(XmlSerializer serializer, String tagName,
   7299                 ArrayList<Signature> pastSignatures) throws IOException {
   7300             if (mSignatures == null) {
   7301                 return;
   7302             }
   7303             serializer.startTag(null, tagName);
   7304             serializer.attribute(null, "count",
   7305                     Integer.toString(mSignatures.length));
   7306             for (int i=0; i<mSignatures.length; i++) {
   7307                 serializer.startTag(null, "cert");
   7308                 final Signature sig = mSignatures[i];
   7309                 final int sigHash = sig.hashCode();
   7310                 final int numPast = pastSignatures.size();
   7311                 int j;
   7312                 for (j=0; j<numPast; j++) {
   7313                     Signature pastSig = pastSignatures.get(j);
   7314                     if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
   7315                         serializer.attribute(null, "index", Integer.toString(j));
   7316                         break;
   7317                     }
   7318                 }
   7319                 if (j >= numPast) {
   7320                     pastSignatures.add(sig);
   7321                     serializer.attribute(null, "index", Integer.toString(numPast));
   7322                     serializer.attribute(null, "key", sig.toCharsString());
   7323                 }
   7324                 serializer.endTag(null, "cert");
   7325             }
   7326             serializer.endTag(null, tagName);
   7327         }
   7328 
   7329         void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
   7330                 throws IOException, XmlPullParserException {
   7331             String countStr = parser.getAttributeValue(null, "count");
   7332             if (countStr == null) {
   7333                 reportSettingsProblem(Log.WARN,
   7334                         "Error in package manager settings: <signatures> has"
   7335                            + " no count at " + parser.getPositionDescription());
   7336                 XmlUtils.skipCurrentTag(parser);
   7337             }
   7338             final int count = Integer.parseInt(countStr);
   7339             mSignatures = new Signature[count];
   7340             int pos = 0;
   7341 
   7342             int outerDepth = parser.getDepth();
   7343             int type;
   7344             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   7345                    && (type != XmlPullParser.END_TAG
   7346                            || parser.getDepth() > outerDepth)) {
   7347                 if (type == XmlPullParser.END_TAG
   7348                         || type == XmlPullParser.TEXT) {
   7349                     continue;
   7350                 }
   7351 
   7352                 String tagName = parser.getName();
   7353                 if (tagName.equals("cert")) {
   7354                     if (pos < count) {
   7355                         String index = parser.getAttributeValue(null, "index");
   7356                         if (index != null) {
   7357                             try {
   7358                                 int idx = Integer.parseInt(index);
   7359                                 String key = parser.getAttributeValue(null, "key");
   7360                                 if (key == null) {
   7361                                     if (idx >= 0 && idx < pastSignatures.size()) {
   7362                                         Signature sig = pastSignatures.get(idx);
   7363                                         if (sig != null) {
   7364                                             mSignatures[pos] = pastSignatures.get(idx);
   7365                                             pos++;
   7366                                         } else {
   7367                                             reportSettingsProblem(Log.WARN,
   7368                                                     "Error in package manager settings: <cert> "
   7369                                                        + "index " + index + " is not defined at "
   7370                                                        + parser.getPositionDescription());
   7371                                         }
   7372                                     } else {
   7373                                         reportSettingsProblem(Log.WARN,
   7374                                                 "Error in package manager settings: <cert> "
   7375                                                    + "index " + index + " is out of bounds at "
   7376                                                    + parser.getPositionDescription());
   7377                                     }
   7378                                 } else {
   7379                                     while (pastSignatures.size() <= idx) {
   7380                                         pastSignatures.add(null);
   7381                                     }
   7382                                     Signature sig = new Signature(key);
   7383                                     pastSignatures.set(idx, sig);
   7384                                     mSignatures[pos] = sig;
   7385                                     pos++;
   7386                                 }
   7387                             } catch (NumberFormatException e) {
   7388                                 reportSettingsProblem(Log.WARN,
   7389                                         "Error in package manager settings: <cert> "
   7390                                            + "index " + index + " is not a number at "
   7391                                            + parser.getPositionDescription());
   7392                             }
   7393                         } else {
   7394                             reportSettingsProblem(Log.WARN,
   7395                                     "Error in package manager settings: <cert> has"
   7396                                        + " no index at " + parser.getPositionDescription());
   7397                         }
   7398                     } else {
   7399                         reportSettingsProblem(Log.WARN,
   7400                                 "Error in package manager settings: too "
   7401                                    + "many <cert> tags, expected " + count
   7402                                    + " at " + parser.getPositionDescription());
   7403                     }
   7404                 } else {
   7405                     reportSettingsProblem(Log.WARN,
   7406                             "Unknown element under <cert>: "
   7407                             + parser.getName());
   7408                 }
   7409                 XmlUtils.skipCurrentTag(parser);
   7410             }
   7411 
   7412             if (pos < count) {
   7413                 // Should never happen -- there is an error in the written
   7414                 // settings -- but if it does we don't want to generate
   7415                 // a bad array.
   7416                 Signature[] newSigs = new Signature[pos];
   7417                 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
   7418                 mSignatures = newSigs;
   7419             }
   7420         }
   7421 
   7422         private void assignSignatures(Signature[] sigs) {
   7423             if (sigs == null) {
   7424                 mSignatures = null;
   7425                 return;
   7426             }
   7427             mSignatures = new Signature[sigs.length];
   7428             for (int i=0; i<sigs.length; i++) {
   7429                 mSignatures[i] = sigs[i];
   7430             }
   7431         }
   7432 
   7433         @Override
   7434         public String toString() {
   7435             StringBuffer buf = new StringBuffer(128);
   7436             buf.append("PackageSignatures{");
   7437             buf.append(Integer.toHexString(System.identityHashCode(this)));
   7438             buf.append(" [");
   7439             if (mSignatures != null) {
   7440                 for (int i=0; i<mSignatures.length; i++) {
   7441                     if (i > 0) buf.append(", ");
   7442                     buf.append(Integer.toHexString(
   7443                             System.identityHashCode(mSignatures[i])));
   7444                 }
   7445             }
   7446             buf.append("]}");
   7447             return buf.toString();
   7448         }
   7449     }
   7450 
   7451     static class PreferredActivity extends IntentFilter {
   7452         final int mMatch;
   7453         final String[] mSetPackages;
   7454         final String[] mSetClasses;
   7455         final String[] mSetComponents;
   7456         final ComponentName mActivity;
   7457         final String mShortActivity;
   7458         String mParseError;
   7459 
   7460         PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
   7461                 ComponentName activity) {
   7462             super(filter);
   7463             mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
   7464             mActivity = activity;
   7465             mShortActivity = activity.flattenToShortString();
   7466             mParseError = null;
   7467             if (set != null) {
   7468                 final int N = set.length;
   7469                 String[] myPackages = new String[N];
   7470                 String[] myClasses = new String[N];
   7471                 String[] myComponents = new String[N];
   7472                 for (int i=0; i<N; i++) {
   7473                     ComponentName cn = set[i];
   7474                     if (cn == null) {
   7475                         mSetPackages = null;
   7476                         mSetClasses = null;
   7477                         mSetComponents = null;
   7478                         return;
   7479                     }
   7480                     myPackages[i] = cn.getPackageName().intern();
   7481                     myClasses[i] = cn.getClassName().intern();
   7482                     myComponents[i] = cn.flattenToShortString().intern();
   7483                 }
   7484                 mSetPackages = myPackages;
   7485                 mSetClasses = myClasses;
   7486                 mSetComponents = myComponents;
   7487             } else {
   7488                 mSetPackages = null;
   7489                 mSetClasses = null;
   7490                 mSetComponents = null;
   7491             }
   7492         }
   7493 
   7494         PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
   7495                 IOException {
   7496             mShortActivity = parser.getAttributeValue(null, "name");
   7497             mActivity = ComponentName.unflattenFromString(mShortActivity);
   7498             if (mActivity == null) {
   7499                 mParseError = "Bad activity name " + mShortActivity;
   7500             }
   7501             String matchStr = parser.getAttributeValue(null, "match");
   7502             mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
   7503             String setCountStr = parser.getAttributeValue(null, "set");
   7504             int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
   7505 
   7506             String[] myPackages = setCount > 0 ? new String[setCount] : null;
   7507             String[] myClasses = setCount > 0 ? new String[setCount] : null;
   7508             String[] myComponents = setCount > 0 ? new String[setCount] : null;
   7509 
   7510             int setPos = 0;
   7511 
   7512             int outerDepth = parser.getDepth();
   7513             int type;
   7514             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   7515                    && (type != XmlPullParser.END_TAG
   7516                            || parser.getDepth() > outerDepth)) {
   7517                 if (type == XmlPullParser.END_TAG
   7518                         || type == XmlPullParser.TEXT) {
   7519                     continue;
   7520                 }
   7521 
   7522                 String tagName = parser.getName();
   7523                 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
   7524                 //        + parser.getDepth() + " tag=" + tagName);
   7525                 if (tagName.equals("set")) {
   7526                     String name = parser.getAttributeValue(null, "name");
   7527                     if (name == null) {
   7528                         if (mParseError == null) {
   7529                             mParseError = "No name in set tag in preferred activity "
   7530                                 + mShortActivity;
   7531                         }
   7532                     } else if (setPos >= setCount) {
   7533                         if (mParseError == null) {
   7534                             mParseError = "Too many set tags in preferred activity "
   7535                                 + mShortActivity;
   7536                         }
   7537                     } else {
   7538                         ComponentName cn = ComponentName.unflattenFromString(name);
   7539                         if (cn == null) {
   7540                             if (mParseError == null) {
   7541                                 mParseError = "Bad set name " + name + " in preferred activity "
   7542                                     + mShortActivity;
   7543                             }
   7544                         } else {
   7545                             myPackages[setPos] = cn.getPackageName();
   7546                             myClasses[setPos] = cn.getClassName();
   7547                             myComponents[setPos] = name;
   7548                             setPos++;
   7549                         }
   7550                     }
   7551                     XmlUtils.skipCurrentTag(parser);
   7552                 } else if (tagName.equals("filter")) {
   7553                     //Log.i(TAG, "Starting to parse filter...");
   7554                     readFromXml(parser);
   7555                     //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
   7556                     //        + parser.getDepth() + " tag=" + parser.getName());
   7557                 } else {
   7558                     reportSettingsProblem(Log.WARN,
   7559                             "Unknown element under <preferred-activities>: "
   7560                             + parser.getName());
   7561                     XmlUtils.skipCurrentTag(parser);
   7562                 }
   7563             }
   7564 
   7565             if (setPos != setCount) {
   7566                 if (mParseError == null) {
   7567                     mParseError = "Not enough set tags (expected " + setCount
   7568                         + " but found " + setPos + ") in " + mShortActivity;
   7569                 }
   7570             }
   7571 
   7572             mSetPackages = myPackages;
   7573             mSetClasses = myClasses;
   7574             mSetComponents = myComponents;
   7575         }
   7576 
   7577         public void writeToXml(XmlSerializer serializer) throws IOException {
   7578             final int NS = mSetClasses != null ? mSetClasses.length : 0;
   7579             serializer.attribute(null, "name", mShortActivity);
   7580             serializer.attribute(null, "match", Integer.toHexString(mMatch));
   7581             serializer.attribute(null, "set", Integer.toString(NS));
   7582             for (int s=0; s<NS; s++) {
   7583                 serializer.startTag(null, "set");
   7584                 serializer.attribute(null, "name", mSetComponents[s]);
   7585                 serializer.endTag(null, "set");
   7586             }
   7587             serializer.startTag(null, "filter");
   7588             super.writeToXml(serializer);
   7589             serializer.endTag(null, "filter");
   7590         }
   7591 
   7592         boolean sameSet(List<ResolveInfo> query, int priority) {
   7593             if (mSetPackages == null) return false;
   7594             final int NQ = query.size();
   7595             final int NS = mSetPackages.length;
   7596             int numMatch = 0;
   7597             for (int i=0; i<NQ; i++) {
   7598                 ResolveInfo ri = query.get(i);
   7599                 if (ri.priority != priority) continue;
   7600                 ActivityInfo ai = ri.activityInfo;
   7601                 boolean good = false;
   7602                 for (int j=0; j<NS; j++) {
   7603                     if (mSetPackages[j].equals(ai.packageName)
   7604                             && mSetClasses[j].equals(ai.name)) {
   7605                         numMatch++;
   7606                         good = true;
   7607                         break;
   7608                     }
   7609                 }
   7610                 if (!good) return false;
   7611             }
   7612             return numMatch == NS;
   7613         }
   7614     }
   7615 
   7616     static class GrantedPermissions {
   7617         int pkgFlags;
   7618 
   7619         HashSet<String> grantedPermissions = new HashSet<String>();
   7620         int[] gids;
   7621 
   7622         GrantedPermissions(int pkgFlags) {
   7623             setFlags(pkgFlags);
   7624         }
   7625 
   7626         void setFlags(int pkgFlags) {
   7627             this.pkgFlags = pkgFlags & (
   7628                     ApplicationInfo.FLAG_SYSTEM |
   7629                     ApplicationInfo.FLAG_FORWARD_LOCK |
   7630                     ApplicationInfo.FLAG_EXTERNAL_STORAGE);
   7631         }
   7632     }
   7633 
   7634     /**
   7635      * Settings base class for pending and resolved classes.
   7636      */
   7637     static class PackageSettingBase extends GrantedPermissions {
   7638         final String name;
   7639         final String realName;
   7640         File codePath;
   7641         String codePathString;
   7642         File resourcePath;
   7643         String resourcePathString;
   7644         private long timeStamp;
   7645         private String timeStampString = "0";
   7646         int versionCode;
   7647 
   7648         boolean uidError;
   7649 
   7650         PackageSignatures signatures = new PackageSignatures();
   7651 
   7652         boolean permissionsFixed;
   7653         boolean haveGids;
   7654 
   7655         /* Explicitly disabled components */
   7656         HashSet<String> disabledComponents = new HashSet<String>(0);
   7657         /* Explicitly enabled components */
   7658         HashSet<String> enabledComponents = new HashSet<String>(0);
   7659         int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
   7660         int installStatus = PKG_INSTALL_COMPLETE;
   7661 
   7662         PackageSettingBase origPackage;
   7663 
   7664         /* package name of the app that installed this package */
   7665         String installerPackageName;
   7666 
   7667         PackageSettingBase(String name, String realName, File codePath, File resourcePath,
   7668                 int pVersionCode, int pkgFlags) {
   7669             super(pkgFlags);
   7670             this.name = name;
   7671             this.realName = realName;
   7672             init(codePath, resourcePath, pVersionCode);
   7673         }
   7674 
   7675         void init(File codePath, File resourcePath, int pVersionCode) {
   7676             this.codePath = codePath;
   7677             this.codePathString = codePath.toString();
   7678             this.resourcePath = resourcePath;
   7679             this.resourcePathString = resourcePath.toString();
   7680             this.versionCode = pVersionCode;
   7681         }
   7682 
   7683         public void setInstallerPackageName(String packageName) {
   7684             installerPackageName = packageName;
   7685         }
   7686 
   7687         String getInstallerPackageName() {
   7688             return installerPackageName;
   7689         }
   7690 
   7691         public void setInstallStatus(int newStatus) {
   7692             installStatus = newStatus;
   7693         }
   7694 
   7695         public int getInstallStatus() {
   7696             return installStatus;
   7697         }
   7698 
   7699         public void setTimeStamp(long newStamp) {
   7700             if (newStamp != timeStamp) {
   7701                 timeStamp = newStamp;
   7702                 timeStampString = Long.toString(newStamp);
   7703             }
   7704         }
   7705 
   7706         public void setTimeStamp(long newStamp, String newStampStr) {
   7707             timeStamp = newStamp;
   7708             timeStampString = newStampStr;
   7709         }
   7710 
   7711         public long getTimeStamp() {
   7712             return timeStamp;
   7713         }
   7714 
   7715         public String getTimeStampStr() {
   7716             return timeStampString;
   7717         }
   7718 
   7719         public void copyFrom(PackageSettingBase base) {
   7720             grantedPermissions = base.grantedPermissions;
   7721             gids = base.gids;
   7722 
   7723             timeStamp = base.timeStamp;
   7724             timeStampString = base.timeStampString;
   7725             signatures = base.signatures;
   7726             permissionsFixed = base.permissionsFixed;
   7727             haveGids = base.haveGids;
   7728             disabledComponents = base.disabledComponents;
   7729             enabledComponents = base.enabledComponents;
   7730             enabled = base.enabled;
   7731             installStatus = base.installStatus;
   7732         }
   7733 
   7734         boolean enableComponentLP(String componentClassName) {
   7735             boolean changed = disabledComponents.remove(componentClassName);
   7736             changed |= enabledComponents.add(componentClassName);
   7737             return changed;
   7738         }
   7739 
   7740         boolean disableComponentLP(String componentClassName) {
   7741             boolean changed = enabledComponents.remove(componentClassName);
   7742             changed |= disabledComponents.add(componentClassName);
   7743             return changed;
   7744         }
   7745 
   7746         boolean restoreComponentLP(String componentClassName) {
   7747             boolean changed = enabledComponents.remove(componentClassName);
   7748             changed |= disabledComponents.remove(componentClassName);
   7749             return changed;
   7750         }
   7751 
   7752         int currentEnabledStateLP(String componentName) {
   7753             if (enabledComponents.contains(componentName)) {
   7754                 return COMPONENT_ENABLED_STATE_ENABLED;
   7755             } else if (disabledComponents.contains(componentName)) {
   7756                 return COMPONENT_ENABLED_STATE_DISABLED;
   7757             } else {
   7758                 return COMPONENT_ENABLED_STATE_DEFAULT;
   7759             }
   7760         }
   7761     }
   7762 
   7763     /**
   7764      * Settings data for a particular package we know about.
   7765      */
   7766     static final class PackageSetting extends PackageSettingBase {
   7767         int userId;
   7768         PackageParser.Package pkg;
   7769         SharedUserSetting sharedUser;
   7770 
   7771         PackageSetting(String name, String realName, File codePath, File resourcePath,
   7772                 int pVersionCode, int pkgFlags) {
   7773             super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
   7774         }
   7775 
   7776         @Override
   7777         public String toString() {
   7778             return "PackageSetting{"
   7779                 + Integer.toHexString(System.identityHashCode(this))
   7780                 + " " + name + "/" + userId + "}";
   7781         }
   7782     }
   7783 
   7784     /**
   7785      * Settings data for a particular shared user ID we know about.
   7786      */
   7787     static final class SharedUserSetting extends GrantedPermissions {
   7788         final String name;
   7789         int userId;
   7790         final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
   7791         final PackageSignatures signatures = new PackageSignatures();
   7792 
   7793         SharedUserSetting(String _name, int _pkgFlags) {
   7794             super(_pkgFlags);
   7795             name = _name;
   7796         }
   7797 
   7798         @Override
   7799         public String toString() {
   7800             return "SharedUserSetting{"
   7801                 + Integer.toHexString(System.identityHashCode(this))
   7802                 + " " + name + "/" + userId + "}";
   7803         }
   7804     }
   7805 
   7806     /**
   7807      * Holds information about dynamic settings.
   7808      */
   7809     private static final class Settings {
   7810         private final File mSettingsFilename;
   7811         private final File mBackupSettingsFilename;
   7812         private final File mPackageListFilename;
   7813         private final HashMap<String, PackageSetting> mPackages =
   7814                 new HashMap<String, PackageSetting>();
   7815         // List of replaced system applications
   7816         final HashMap<String, PackageSetting> mDisabledSysPackages =
   7817             new HashMap<String, PackageSetting>();
   7818 
   7819         // These are the last platform API version we were using for
   7820         // the apps installed on internal and external storage.  It is
   7821         // used to grant newer permissions one time during a system upgrade.
   7822         int mInternalSdkPlatform;
   7823         int mExternalSdkPlatform;
   7824 
   7825         // The user's preferred activities associated with particular intent
   7826         // filters.
   7827         private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
   7828                     new IntentResolver<PreferredActivity, PreferredActivity>() {
   7829             @Override
   7830             protected String packageForFilter(PreferredActivity filter) {
   7831                 return filter.mActivity.getPackageName();
   7832             }
   7833             @Override
   7834             protected void dumpFilter(PrintWriter out, String prefix,
   7835                     PreferredActivity filter) {
   7836                 out.print(prefix); out.print(
   7837                         Integer.toHexString(System.identityHashCode(filter)));
   7838                         out.print(' ');
   7839                         out.print(filter.mActivity.flattenToShortString());
   7840                         out.print(" match=0x");
   7841                         out.println( Integer.toHexString(filter.mMatch));
   7842                 if (filter.mSetComponents != null) {
   7843                     out.print(prefix); out.println("  Selected from:");
   7844                     for (int i=0; i<filter.mSetComponents.length; i++) {
   7845                         out.print(prefix); out.print("    ");
   7846                                 out.println(filter.mSetComponents[i]);
   7847                     }
   7848                 }
   7849             }
   7850         };
   7851         private final HashMap<String, SharedUserSetting> mSharedUsers =
   7852                 new HashMap<String, SharedUserSetting>();
   7853         private final ArrayList<Object> mUserIds = new ArrayList<Object>();
   7854         private final SparseArray<Object> mOtherUserIds =
   7855                 new SparseArray<Object>();
   7856 
   7857         // For reading/writing settings file.
   7858         private final ArrayList<Signature> mPastSignatures =
   7859                 new ArrayList<Signature>();
   7860 
   7861         // Mapping from permission names to info about them.
   7862         final HashMap<String, BasePermission> mPermissions =
   7863                 new HashMap<String, BasePermission>();
   7864 
   7865         // Mapping from permission tree names to info about them.
   7866         final HashMap<String, BasePermission> mPermissionTrees =
   7867                 new HashMap<String, BasePermission>();
   7868 
   7869         // Packages that have been uninstalled and still need their external
   7870         // storage data deleted.
   7871         final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
   7872 
   7873         // Packages that have been renamed since they were first installed.
   7874         // Keys are the new names of the packages, values are the original
   7875         // names.  The packages appear everwhere else under their original
   7876         // names.
   7877         final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
   7878 
   7879         private final StringBuilder mReadMessages = new StringBuilder();
   7880 
   7881         private static final class PendingPackage extends PackageSettingBase {
   7882             final int sharedId;
   7883 
   7884             PendingPackage(String name, String realName, File codePath, File resourcePath,
   7885                     int sharedId, int pVersionCode, int pkgFlags) {
   7886                 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
   7887                 this.sharedId = sharedId;
   7888             }
   7889         }
   7890         private final ArrayList<PendingPackage> mPendingPackages
   7891                 = new ArrayList<PendingPackage>();
   7892 
   7893         Settings() {
   7894             File dataDir = Environment.getDataDirectory();
   7895             File systemDir = new File(dataDir, "system");
   7896             // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
   7897             systemDir.mkdirs();
   7898             FileUtils.setPermissions(systemDir.toString(),
   7899                     FileUtils.S_IRWXU|FileUtils.S_IRWXG
   7900                     |FileUtils.S_IROTH|FileUtils.S_IXOTH,
   7901                     -1, -1);
   7902             mSettingsFilename = new File(systemDir, "packages.xml");
   7903             mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
   7904             mPackageListFilename = new File(systemDir, "packages.list");
   7905         }
   7906 
   7907         PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
   7908                 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
   7909                 int pkgFlags, boolean create, boolean add) {
   7910             final String name = pkg.packageName;
   7911             PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
   7912                     resourcePath, pkg.mVersionCode, pkgFlags, create, add);
   7913             return p;
   7914         }
   7915 
   7916         PackageSetting peekPackageLP(String name) {
   7917             return mPackages.get(name);
   7918             /*
   7919             PackageSetting p = mPackages.get(name);
   7920             if (p != null && p.codePath.getPath().equals(codePath)) {
   7921                 return p;
   7922             }
   7923             return null;
   7924             */
   7925         }
   7926 
   7927         void setInstallStatus(String pkgName, int status) {
   7928             PackageSetting p = mPackages.get(pkgName);
   7929             if(p != null) {
   7930                 if(p.getInstallStatus() != status) {
   7931                     p.setInstallStatus(status);
   7932                 }
   7933             }
   7934         }
   7935 
   7936         void setInstallerPackageName(String pkgName,
   7937                 String installerPkgName) {
   7938             PackageSetting p = mPackages.get(pkgName);
   7939             if(p != null) {
   7940                 p.setInstallerPackageName(installerPkgName);
   7941             }
   7942         }
   7943 
   7944         String getInstallerPackageName(String pkgName) {
   7945             PackageSetting p = mPackages.get(pkgName);
   7946             return (p == null) ? null : p.getInstallerPackageName();
   7947         }
   7948 
   7949         int getInstallStatus(String pkgName) {
   7950             PackageSetting p = mPackages.get(pkgName);
   7951             if(p != null) {
   7952                 return p.getInstallStatus();
   7953             }
   7954             return -1;
   7955         }
   7956 
   7957         SharedUserSetting getSharedUserLP(String name,
   7958                 int pkgFlags, boolean create) {
   7959             SharedUserSetting s = mSharedUsers.get(name);
   7960             if (s == null) {
   7961                 if (!create) {
   7962                     return null;
   7963                 }
   7964                 s = new SharedUserSetting(name, pkgFlags);
   7965                 if (MULTIPLE_APPLICATION_UIDS) {
   7966                     s.userId = newUserIdLP(s);
   7967                 } else {
   7968                     s.userId = FIRST_APPLICATION_UID;
   7969                 }
   7970                 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
   7971                 // < 0 means we couldn't assign a userid; fall out and return
   7972                 // s, which is currently null
   7973                 if (s.userId >= 0) {
   7974                     mSharedUsers.put(name, s);
   7975                 }
   7976             }
   7977 
   7978             return s;
   7979         }
   7980 
   7981         int disableSystemPackageLP(String name) {
   7982             PackageSetting p = mPackages.get(name);
   7983             if(p == null) {
   7984                 Log.w(TAG, "Package:"+name+" is not an installed package");
   7985                 return -1;
   7986             }
   7987             PackageSetting dp = mDisabledSysPackages.get(name);
   7988             // always make sure the system package code and resource paths dont change
   7989             if(dp == null) {
   7990                 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
   7991                     p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
   7992                 }
   7993                 mDisabledSysPackages.put(name, p);
   7994             }
   7995             return removePackageLP(name);
   7996         }
   7997 
   7998         PackageSetting enableSystemPackageLP(String name) {
   7999             PackageSetting p = mDisabledSysPackages.get(name);
   8000             if(p == null) {
   8001                 Log.w(TAG, "Package:"+name+" is not disabled");
   8002                 return null;
   8003             }
   8004             // Reset flag in ApplicationInfo object
   8005             if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
   8006                 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
   8007             }
   8008             PackageSetting ret = addPackageLP(name, p.realName, p.codePath,
   8009                     p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
   8010             mDisabledSysPackages.remove(name);
   8011             return ret;
   8012         }
   8013 
   8014         PackageSetting addPackageLP(String name, String realName, File codePath,
   8015                 File resourcePath, int uid, int vc, int pkgFlags) {
   8016             PackageSetting p = mPackages.get(name);
   8017             if (p != null) {
   8018                 if (p.userId == uid) {
   8019                     return p;
   8020                 }
   8021                 reportSettingsProblem(Log.ERROR,
   8022                         "Adding duplicate package, keeping first: " + name);
   8023                 return null;
   8024             }
   8025             p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
   8026             p.userId = uid;
   8027             if (addUserIdLP(uid, p, name)) {
   8028                 mPackages.put(name, p);
   8029                 return p;
   8030             }
   8031             return null;
   8032         }
   8033 
   8034         SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
   8035             SharedUserSetting s = mSharedUsers.get(name);
   8036             if (s != null) {
   8037                 if (s.userId == uid) {
   8038                     return s;
   8039                 }
   8040                 reportSettingsProblem(Log.ERROR,
   8041                         "Adding duplicate shared user, keeping first: " + name);
   8042                 return null;
   8043             }
   8044             s = new SharedUserSetting(name, pkgFlags);
   8045             s.userId = uid;
   8046             if (addUserIdLP(uid, s, name)) {
   8047                 mSharedUsers.put(name, s);
   8048                 return s;
   8049             }
   8050             return null;
   8051         }
   8052 
   8053         // Transfer ownership of permissions from one package to another.
   8054         private void transferPermissions(String origPkg, String newPkg) {
   8055             // Transfer ownership of permissions to the new package.
   8056             for (int i=0; i<2; i++) {
   8057                 HashMap<String, BasePermission> permissions =
   8058                         i == 0 ? mPermissionTrees : mPermissions;
   8059                 for (BasePermission bp : permissions.values()) {
   8060                     if (origPkg.equals(bp.sourcePackage)) {
   8061                         if (DEBUG_UPGRADE) Log.v(TAG,
   8062                                 "Moving permission " + bp.name
   8063                                 + " from pkg " + bp.sourcePackage
   8064                                 + " to " + newPkg);
   8065                         bp.sourcePackage = newPkg;
   8066                         bp.packageSetting = null;
   8067                         bp.perm = null;
   8068                         if (bp.pendingInfo != null) {
   8069                             bp.pendingInfo.packageName = newPkg;
   8070                         }
   8071                         bp.uid = 0;
   8072                         bp.gids = null;
   8073                     }
   8074                 }
   8075             }
   8076         }
   8077 
   8078         private PackageSetting getPackageLP(String name, PackageSetting origPackage,
   8079                 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
   8080                 int vc, int pkgFlags, boolean create, boolean add) {
   8081             PackageSetting p = mPackages.get(name);
   8082             if (p != null) {
   8083                 if (!p.codePath.equals(codePath)) {
   8084                     // Check to see if its a disabled system app
   8085                     if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
   8086                         // This is an updated system app with versions in both system
   8087                         // and data partition. Just let the most recent version
   8088                         // take precedence.
   8089                         Slog.w(TAG, "Trying to update system app code path from " +
   8090                                 p.codePathString + " to " + codePath.toString());
   8091                     } else {
   8092                         // Just a change in the code path is not an issue, but
   8093                         // let's log a message about it.
   8094                         Slog.i(TAG, "Package " + name + " codePath changed from " + p.codePath
   8095                                 + " to " + codePath + "; Retaining data and using new");
   8096                     }
   8097                 }
   8098                 if (p.sharedUser != sharedUser) {
   8099                     reportSettingsProblem(Log.WARN,
   8100                             "Package " + name + " shared user changed from "
   8101                             + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
   8102                             + " to "
   8103                             + (sharedUser != null ? sharedUser.name : "<nothing>")
   8104                             + "; replacing with new");
   8105                     p = null;
   8106                 } else {
   8107                     if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
   8108                         // If what we are scanning is a system package, then
   8109                         // make it so, regardless of whether it was previously
   8110                         // installed only in the data partition.
   8111                         p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
   8112                     }
   8113                 }
   8114             }
   8115             if (p == null) {
   8116                 // Create a new PackageSettings entry. this can end up here because
   8117                 // of code path mismatch or user id mismatch of an updated system partition
   8118                 if (!create) {
   8119                     return null;
   8120                 }
   8121                 if (origPackage != null) {
   8122                     // We are consuming the data from an existing package.
   8123                     p = new PackageSetting(origPackage.name, name, codePath,
   8124                             resourcePath, vc, pkgFlags);
   8125                     if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
   8126                             + " is adopting original package " + origPackage.name);
   8127                     // Note that we will retain the new package's signature so
   8128                     // that we can keep its data.
   8129                     PackageSignatures s = p.signatures;
   8130                     p.copyFrom(origPackage);
   8131                     p.signatures = s;
   8132                     p.sharedUser = origPackage.sharedUser;
   8133                     p.userId = origPackage.userId;
   8134                     p.origPackage = origPackage;
   8135                     mRenamedPackages.put(name, origPackage.name);
   8136                     name = origPackage.name;
   8137                     // Update new package state.
   8138                     p.setTimeStamp(codePath.lastModified());
   8139                 } else {
   8140                     p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
   8141                     p.setTimeStamp(codePath.lastModified());
   8142                     p.sharedUser = sharedUser;
   8143                     if (sharedUser != null) {
   8144                         p.userId = sharedUser.userId;
   8145                     } else if (MULTIPLE_APPLICATION_UIDS) {
   8146                         // Clone the setting here for disabled system packages
   8147                         PackageSetting dis = mDisabledSysPackages.get(name);
   8148                         if (dis != null) {
   8149                             // For disabled packages a new setting is created
   8150                             // from the existing user id. This still has to be
   8151                             // added to list of user id's
   8152                             // Copy signatures from previous setting
   8153                             if (dis.signatures.mSignatures != null) {
   8154                                 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
   8155                             }
   8156                             p.userId = dis.userId;
   8157                             // Clone permissions
   8158                             p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
   8159                             // Clone component info
   8160                             p.disabledComponents = new HashSet<String>(dis.disabledComponents);
   8161                             p.enabledComponents = new HashSet<String>(dis.enabledComponents);
   8162                             // Add new setting to list of user ids
   8163                             addUserIdLP(p.userId, p, name);
   8164                         } else {
   8165                             // Assign new user id
   8166                             p.userId = newUserIdLP(p);
   8167                         }
   8168                     } else {
   8169                         p.userId = FIRST_APPLICATION_UID;
   8170                     }
   8171                 }
   8172                 if (p.userId < 0) {
   8173                     reportSettingsProblem(Log.WARN,
   8174                             "Package " + name + " could not be assigned a valid uid");
   8175                     return null;
   8176                 }
   8177                 if (add) {
   8178                     // Finish adding new package by adding it and updating shared
   8179                     // user preferences
   8180                     addPackageSettingLP(p, name, sharedUser);
   8181                 }
   8182             }
   8183             return p;
   8184         }
   8185 
   8186         private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
   8187             p.pkg = pkg;
   8188             String codePath = pkg.applicationInfo.sourceDir;
   8189             String resourcePath = pkg.applicationInfo.publicSourceDir;
   8190             // Update code path if needed
   8191             if (!codePath.equalsIgnoreCase(p.codePathString)) {
   8192                 Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
   8193                         " changing from " + p.codePathString + " to " + codePath);
   8194                 p.codePath = new File(codePath);
   8195                 p.codePathString = codePath;
   8196             }
   8197             //Update resource path if needed
   8198             if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
   8199                 Slog.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
   8200                         " changing from " + p.resourcePathString + " to " + resourcePath);
   8201                 p.resourcePath = new File(resourcePath);
   8202                 p.resourcePathString = resourcePath;
   8203             }
   8204             // Update version code if needed
   8205              if (pkg.mVersionCode != p.versionCode) {
   8206                 p.versionCode = pkg.mVersionCode;
   8207             }
   8208              // Update signatures if needed.
   8209              if (p.signatures.mSignatures == null) {
   8210                  p.signatures.assignSignatures(pkg.mSignatures);
   8211              }
   8212              // If this app defines a shared user id initialize
   8213              // the shared user signatures as well.
   8214              if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
   8215                  p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
   8216              }
   8217             addPackageSettingLP(p, pkg.packageName, p.sharedUser);
   8218         }
   8219 
   8220         // Utility method that adds a PackageSetting to mPackages and
   8221         // completes updating the shared user attributes
   8222         private void addPackageSettingLP(PackageSetting p, String name,
   8223                 SharedUserSetting sharedUser) {
   8224             mPackages.put(name, p);
   8225             if (sharedUser != null) {
   8226                 if (p.sharedUser != null && p.sharedUser != sharedUser) {
   8227                     reportSettingsProblem(Log.ERROR,
   8228                             "Package " + p.name + " was user "
   8229                             + p.sharedUser + " but is now " + sharedUser
   8230                             + "; I am not changing its files so it will probably fail!");
   8231                     p.sharedUser.packages.remove(p);
   8232                 } else if (p.userId != sharedUser.userId) {
   8233                     reportSettingsProblem(Log.ERROR,
   8234                         "Package " + p.name + " was user id " + p.userId
   8235                         + " but is now user " + sharedUser
   8236                         + " with id " + sharedUser.userId
   8237                         + "; I am not changing its files so it will probably fail!");
   8238                 }
   8239 
   8240                 sharedUser.packages.add(p);
   8241                 p.sharedUser = sharedUser;
   8242                 p.userId = sharedUser.userId;
   8243             }
   8244         }
   8245 
   8246         /*
   8247          * Update the shared user setting when a package using
   8248          * specifying the shared user id is removed. The gids
   8249          * associated with each permission of the deleted package
   8250          * are removed from the shared user's gid list only if its
   8251          * not in use by other permissions of packages in the
   8252          * shared user setting.
   8253          */
   8254         private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
   8255             if ( (deletedPs == null) || (deletedPs.pkg == null)) {
   8256                 Slog.i(TAG, "Trying to update info for null package. Just ignoring");
   8257                 return;
   8258             }
   8259             // No sharedUserId
   8260             if (deletedPs.sharedUser == null) {
   8261                 return;
   8262             }
   8263             SharedUserSetting sus = deletedPs.sharedUser;
   8264             // Update permissions
   8265             for (String eachPerm: deletedPs.pkg.requestedPermissions) {
   8266                 boolean used = false;
   8267                 if (!sus.grantedPermissions.contains (eachPerm)) {
   8268                     continue;
   8269                 }
   8270                 for (PackageSetting pkg:sus.packages) {
   8271                     if (pkg.pkg != null &&
   8272                             !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) &&
   8273                             pkg.pkg.requestedPermissions.contains(eachPerm)) {
   8274                         used = true;
   8275                         break;
   8276                     }
   8277                 }
   8278                 if (!used) {
   8279                     // can safely delete this permission from list
   8280                     sus.grantedPermissions.remove(eachPerm);
   8281                 }
   8282             }
   8283             // Update gids
   8284             int newGids[] = globalGids;
   8285             for (String eachPerm : sus.grantedPermissions) {
   8286                 BasePermission bp = mPermissions.get(eachPerm);
   8287                 if (bp != null) {
   8288                     newGids = appendInts(newGids, bp.gids);
   8289                 }
   8290             }
   8291             sus.gids = newGids;
   8292         }
   8293 
   8294         private int removePackageLP(String name) {
   8295             PackageSetting p = mPackages.get(name);
   8296             if (p != null) {
   8297                 mPackages.remove(name);
   8298                 if (p.sharedUser != null) {
   8299                     p.sharedUser.packages.remove(p);
   8300                     if (p.sharedUser.packages.size() == 0) {
   8301                         mSharedUsers.remove(p.sharedUser.name);
   8302                         removeUserIdLP(p.sharedUser.userId);
   8303                         return p.sharedUser.userId;
   8304                     }
   8305                 } else {
   8306                     removeUserIdLP(p.userId);
   8307                     return p.userId;
   8308                 }
   8309             }
   8310             return -1;
   8311         }
   8312 
   8313         private boolean addUserIdLP(int uid, Object obj, Object name) {
   8314             if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
   8315                 return false;
   8316             }
   8317 
   8318             if (uid >= FIRST_APPLICATION_UID) {
   8319                 int N = mUserIds.size();
   8320                 final int index = uid - FIRST_APPLICATION_UID;
   8321                 while (index >= N) {
   8322                     mUserIds.add(null);
   8323                     N++;
   8324                 }
   8325                 if (mUserIds.get(index) != null) {
   8326                     reportSettingsProblem(Log.ERROR,
   8327                             "Adding duplicate user id: " + uid
   8328                             + " name=" + name);
   8329                     return false;
   8330                 }
   8331                 mUserIds.set(index, obj);
   8332             } else {
   8333                 if (mOtherUserIds.get(uid) != null) {
   8334                     reportSettingsProblem(Log.ERROR,
   8335                             "Adding duplicate shared id: " + uid
   8336                             + " name=" + name);
   8337                     return false;
   8338                 }
   8339                 mOtherUserIds.put(uid, obj);
   8340             }
   8341             return true;
   8342         }
   8343 
   8344         public Object getUserIdLP(int uid) {
   8345             if (uid >= FIRST_APPLICATION_UID) {
   8346                 int N = mUserIds.size();
   8347                 final int index = uid - FIRST_APPLICATION_UID;
   8348                 return index < N ? mUserIds.get(index) : null;
   8349             } else {
   8350                 return mOtherUserIds.get(uid);
   8351             }
   8352         }
   8353 
   8354         private Set<String> findPackagesWithFlag(int flag) {
   8355             Set<String> ret = new HashSet<String>();
   8356             for (PackageSetting ps : mPackages.values()) {
   8357                 // Has to match atleast all the flag bits set on flag
   8358                 if ((ps.pkgFlags & flag) == flag) {
   8359                     ret.add(ps.name);
   8360                 }
   8361             }
   8362             return ret;
   8363         }
   8364 
   8365         private void removeUserIdLP(int uid) {
   8366             if (uid >= FIRST_APPLICATION_UID) {
   8367                 int N = mUserIds.size();
   8368                 final int index = uid - FIRST_APPLICATION_UID;
   8369                 if (index < N) mUserIds.set(index, null);
   8370             } else {
   8371                 mOtherUserIds.remove(uid);
   8372             }
   8373         }
   8374 
   8375         void writeLP() {
   8376             //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
   8377 
   8378             // Keep the old settings around until we know the new ones have
   8379             // been successfully written.
   8380             if (mSettingsFilename.exists()) {
   8381                 // Presence of backup settings file indicates that we failed
   8382                 // to persist settings earlier. So preserve the older
   8383                 // backup for future reference since the current settings
   8384                 // might have been corrupted.
   8385                 if (!mBackupSettingsFilename.exists()) {
   8386                     if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
   8387                         Slog.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
   8388                         return;
   8389                     }
   8390                 } else {
   8391                     mSettingsFilename.delete();
   8392                     Slog.w(TAG, "Preserving older settings backup");
   8393                 }
   8394             }
   8395 
   8396             mPastSignatures.clear();
   8397 
   8398             try {
   8399                 FileOutputStream str = new FileOutputStream(mSettingsFilename);
   8400 
   8401                 //XmlSerializer serializer = XmlUtils.serializerInstance();
   8402                 XmlSerializer serializer = new FastXmlSerializer();
   8403                 serializer.setOutput(str, "utf-8");
   8404                 serializer.startDocument(null, true);
   8405                 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
   8406 
   8407                 serializer.startTag(null, "packages");
   8408 
   8409                 serializer.startTag(null, "last-platform-version");
   8410                 serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
   8411                 serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
   8412                 serializer.endTag(null, "last-platform-version");
   8413 
   8414                 serializer.startTag(null, "permission-trees");
   8415                 for (BasePermission bp : mPermissionTrees.values()) {
   8416                     writePermission(serializer, bp);
   8417                 }
   8418                 serializer.endTag(null, "permission-trees");
   8419 
   8420                 serializer.startTag(null, "permissions");
   8421                 for (BasePermission bp : mPermissions.values()) {
   8422                     writePermission(serializer, bp);
   8423                 }
   8424                 serializer.endTag(null, "permissions");
   8425 
   8426                 for (PackageSetting pkg : mPackages.values()) {
   8427                     writePackage(serializer, pkg);
   8428                 }
   8429 
   8430                 for (PackageSetting pkg : mDisabledSysPackages.values()) {
   8431                     writeDisabledSysPackage(serializer, pkg);
   8432                 }
   8433 
   8434                 serializer.startTag(null, "preferred-activities");
   8435                 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
   8436                     serializer.startTag(null, "item");
   8437                     pa.writeToXml(serializer);
   8438                     serializer.endTag(null, "item");
   8439                 }
   8440                 serializer.endTag(null, "preferred-activities");
   8441 
   8442                 for (SharedUserSetting usr : mSharedUsers.values()) {
   8443                     serializer.startTag(null, "shared-user");
   8444                     serializer.attribute(null, "name", usr.name);
   8445                     serializer.attribute(null, "userId",
   8446                             Integer.toString(usr.userId));
   8447                     usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
   8448                     serializer.startTag(null, "perms");
   8449                     for (String name : usr.grantedPermissions) {
   8450                         serializer.startTag(null, "item");
   8451                         serializer.attribute(null, "name", name);
   8452                         serializer.endTag(null, "item");
   8453                     }
   8454                     serializer.endTag(null, "perms");
   8455                     serializer.endTag(null, "shared-user");
   8456                 }
   8457 
   8458                 if (mPackagesToBeCleaned.size() > 0) {
   8459                     for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
   8460                         serializer.startTag(null, "cleaning-package");
   8461                         serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
   8462                         serializer.endTag(null, "cleaning-package");
   8463                     }
   8464                 }
   8465 
   8466                 if (mRenamedPackages.size() > 0) {
   8467                     for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
   8468                         serializer.startTag(null, "renamed-package");
   8469                         serializer.attribute(null, "new", e.getKey());
   8470                         serializer.attribute(null, "old", e.getValue());
   8471                         serializer.endTag(null, "renamed-package");
   8472                     }
   8473                 }
   8474 
   8475                 serializer.endTag(null, "packages");
   8476 
   8477                 serializer.endDocument();
   8478 
   8479                 str.flush();
   8480                 str.close();
   8481 
   8482                 // New settings successfully written, old ones are no longer
   8483                 // needed.
   8484                 mBackupSettingsFilename.delete();
   8485                 FileUtils.setPermissions(mSettingsFilename.toString(),
   8486                         FileUtils.S_IRUSR|FileUtils.S_IWUSR
   8487                         |FileUtils.S_IRGRP|FileUtils.S_IWGRP
   8488                         |FileUtils.S_IROTH,
   8489                         -1, -1);
   8490 
   8491                 // Write package list file now, use a JournaledFile.
   8492                 //
   8493                 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
   8494                 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
   8495 
   8496                 str = new FileOutputStream(journal.chooseForWrite());
   8497                 try {
   8498                     StringBuilder sb = new StringBuilder();
   8499                     for (PackageSetting pkg : mPackages.values()) {
   8500                         ApplicationInfo ai = pkg.pkg.applicationInfo;
   8501                         String  dataPath = ai.dataDir;
   8502                         boolean isDebug  = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
   8503 
   8504                         // Avoid any application that has a space in its path
   8505                         // or that is handled by the system.
   8506                         if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
   8507                             continue;
   8508 
   8509                         // we store on each line the following information for now:
   8510                         //
   8511                         // pkgName    - package name
   8512                         // userId     - application-specific user id
   8513                         // debugFlag  - 0 or 1 if the package is debuggable.
   8514                         // dataPath   - path to package's data path
   8515                         //
   8516                         // NOTE: We prefer not to expose all ApplicationInfo flags for now.
   8517                         //
   8518                         // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
   8519                         // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
   8520                         //   system/core/run-as/run-as.c
   8521                         //
   8522                         sb.setLength(0);
   8523                         sb.append(ai.packageName);
   8524                         sb.append(" ");
   8525                         sb.append((int)ai.uid);
   8526                         sb.append(isDebug ? " 1 " : " 0 ");
   8527                         sb.append(dataPath);
   8528                         sb.append("\n");
   8529                         str.write(sb.toString().getBytes());
   8530                     }
   8531                     str.flush();
   8532                     str.close();
   8533                     journal.commit();
   8534                 }
   8535                 catch (Exception  e) {
   8536                     journal.rollback();
   8537                 }
   8538 
   8539                 FileUtils.setPermissions(mPackageListFilename.toString(),
   8540                         FileUtils.S_IRUSR|FileUtils.S_IWUSR
   8541                         |FileUtils.S_IRGRP|FileUtils.S_IWGRP
   8542                         |FileUtils.S_IROTH,
   8543                         -1, -1);
   8544 
   8545                 return;
   8546 
   8547             } catch(XmlPullParserException e) {
   8548                 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
   8549             } catch(java.io.IOException e) {
   8550                 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
   8551             }
   8552             // Clean up partially written files
   8553             if (mSettingsFilename.exists()) {
   8554                 if (!mSettingsFilename.delete()) {
   8555                     Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
   8556                 }
   8557             }
   8558             //Debug.stopMethodTracing();
   8559         }
   8560 
   8561         void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
   8562                 throws java.io.IOException {
   8563             serializer.startTag(null, "updated-package");
   8564             serializer.attribute(null, "name", pkg.name);
   8565             if (pkg.realName != null) {
   8566                 serializer.attribute(null, "realName", pkg.realName);
   8567             }
   8568             serializer.attribute(null, "codePath", pkg.codePathString);
   8569             serializer.attribute(null, "ts", pkg.getTimeStampStr());
   8570             serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
   8571             if (!pkg.resourcePathString.equals(pkg.codePathString)) {
   8572                 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
   8573             }
   8574             if (pkg.sharedUser == null) {
   8575                 serializer.attribute(null, "userId",
   8576                         Integer.toString(pkg.userId));
   8577             } else {
   8578                 serializer.attribute(null, "sharedUserId",
   8579                         Integer.toString(pkg.userId));
   8580             }
   8581             serializer.startTag(null, "perms");
   8582             if (pkg.sharedUser == null) {
   8583                 // If this is a shared user, the permissions will
   8584                 // be written there.  We still need to write an
   8585                 // empty permissions list so permissionsFixed will
   8586                 // be set.
   8587                 for (final String name : pkg.grantedPermissions) {
   8588                     BasePermission bp = mPermissions.get(name);
   8589                     if (bp != null) {
   8590                         // We only need to write signature or system permissions but this wont
   8591                         // match the semantics of grantedPermissions. So write all permissions.
   8592                         serializer.startTag(null, "item");
   8593                         serializer.attribute(null, "name", name);
   8594                         serializer.endTag(null, "item");
   8595                     }
   8596                 }
   8597             }
   8598             serializer.endTag(null, "perms");
   8599             serializer.endTag(null, "updated-package");
   8600         }
   8601 
   8602         void writePackage(XmlSerializer serializer, final PackageSetting pkg)
   8603                 throws java.io.IOException {
   8604             serializer.startTag(null, "package");
   8605             serializer.attribute(null, "name", pkg.name);
   8606             if (pkg.realName != null) {
   8607                 serializer.attribute(null, "realName", pkg.realName);
   8608             }
   8609             serializer.attribute(null, "codePath", pkg.codePathString);
   8610             if (!pkg.resourcePathString.equals(pkg.codePathString)) {
   8611                 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
   8612             }
   8613             serializer.attribute(null, "flags",
   8614                     Integer.toString(pkg.pkgFlags));
   8615             serializer.attribute(null, "ts", pkg.getTimeStampStr());
   8616             serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
   8617             if (pkg.sharedUser == null) {
   8618                 serializer.attribute(null, "userId",
   8619                         Integer.toString(pkg.userId));
   8620             } else {
   8621                 serializer.attribute(null, "sharedUserId",
   8622                         Integer.toString(pkg.userId));
   8623             }
   8624             if (pkg.uidError) {
   8625                 serializer.attribute(null, "uidError", "true");
   8626             }
   8627             if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
   8628                 serializer.attribute(null, "enabled",
   8629                         pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
   8630                         ? "true" : "false");
   8631             }
   8632             if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
   8633                 serializer.attribute(null, "installStatus", "false");
   8634             }
   8635             if (pkg.installerPackageName != null) {
   8636                 serializer.attribute(null, "installer", pkg.installerPackageName);
   8637             }
   8638             pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
   8639             if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
   8640                 serializer.startTag(null, "perms");
   8641                 if (pkg.sharedUser == null) {
   8642                     // If this is a shared user, the permissions will
   8643                     // be written there.  We still need to write an
   8644                     // empty permissions list so permissionsFixed will
   8645                     // be set.
   8646                     for (final String name : pkg.grantedPermissions) {
   8647                         serializer.startTag(null, "item");
   8648                         serializer.attribute(null, "name", name);
   8649                         serializer.endTag(null, "item");
   8650                     }
   8651                 }
   8652                 serializer.endTag(null, "perms");
   8653             }
   8654             if (pkg.disabledComponents.size() > 0) {
   8655                 serializer.startTag(null, "disabled-components");
   8656                 for (final String name : pkg.disabledComponents) {
   8657                     serializer.startTag(null, "item");
   8658                     serializer.attribute(null, "name", name);
   8659                     serializer.endTag(null, "item");
   8660                 }
   8661                 serializer.endTag(null, "disabled-components");
   8662             }
   8663             if (pkg.enabledComponents.size() > 0) {
   8664                 serializer.startTag(null, "enabled-components");
   8665                 for (final String name : pkg.enabledComponents) {
   8666                     serializer.startTag(null, "item");
   8667                     serializer.attribute(null, "name", name);
   8668                     serializer.endTag(null, "item");
   8669                 }
   8670                 serializer.endTag(null, "enabled-components");
   8671             }
   8672 
   8673             serializer.endTag(null, "package");
   8674         }
   8675 
   8676         void writePermission(XmlSerializer serializer, BasePermission bp)
   8677                 throws XmlPullParserException, java.io.IOException {
   8678             if (bp.type != BasePermission.TYPE_BUILTIN
   8679                     && bp.sourcePackage != null) {
   8680                 serializer.startTag(null, "item");
   8681                 serializer.attribute(null, "name", bp.name);
   8682                 serializer.attribute(null, "package", bp.sourcePackage);
   8683                 if (bp.protectionLevel !=
   8684                         PermissionInfo.PROTECTION_NORMAL) {
   8685                     serializer.attribute(null, "protection",
   8686                             Integer.toString(bp.protectionLevel));
   8687                 }
   8688                 if (DEBUG_SETTINGS) Log.v(TAG,
   8689                         "Writing perm: name=" + bp.name + " type=" + bp.type);
   8690                 if (bp.type == BasePermission.TYPE_DYNAMIC) {
   8691                     PermissionInfo pi = bp.perm != null ? bp.perm.info
   8692                             : bp.pendingInfo;
   8693                     if (pi != null) {
   8694                         serializer.attribute(null, "type", "dynamic");
   8695                         if (pi.icon != 0) {
   8696                             serializer.attribute(null, "icon",
   8697                                     Integer.toString(pi.icon));
   8698                         }
   8699                         if (pi.nonLocalizedLabel != null) {
   8700                             serializer.attribute(null, "label",
   8701                                     pi.nonLocalizedLabel.toString());
   8702                         }
   8703                     }
   8704                 }
   8705                 serializer.endTag(null, "item");
   8706             }
   8707         }
   8708 
   8709         String getReadMessagesLP() {
   8710             return mReadMessages.toString();
   8711         }
   8712 
   8713         ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
   8714             HashSet<String> kList = new HashSet<String>(mPackages.keySet());
   8715             Iterator<String> its = kList.iterator();
   8716             ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
   8717             while(its.hasNext()) {
   8718                 String key = its.next();
   8719                 PackageSetting ps = mPackages.get(key);
   8720                 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
   8721                     ret.add(ps);
   8722                 }
   8723             }
   8724             return ret;
   8725         }
   8726 
   8727         boolean readLP() {
   8728             FileInputStream str = null;
   8729             if (mBackupSettingsFilename.exists()) {
   8730                 try {
   8731                     str = new FileInputStream(mBackupSettingsFilename);
   8732                     mReadMessages.append("Reading from backup settings file\n");
   8733                     Log.i(TAG, "Reading from backup settings file!");
   8734                     if (mSettingsFilename.exists()) {
   8735                         // If both the backup and settings file exist, we
   8736                         // ignore the settings since it might have been
   8737                         // corrupted.
   8738                         Slog.w(TAG, "Cleaning up settings file " + mSettingsFilename);
   8739                         mSettingsFilename.delete();
   8740                     }
   8741                 } catch (java.io.IOException e) {
   8742                     // We'll try for the normal settings file.
   8743                 }
   8744             }
   8745 
   8746             mPastSignatures.clear();
   8747 
   8748             try {
   8749                 if (str == null) {
   8750                     if (!mSettingsFilename.exists()) {
   8751                         mReadMessages.append("No settings file found\n");
   8752                         Slog.i(TAG, "No current settings file!");
   8753                         return false;
   8754                     }
   8755                     str = new FileInputStream(mSettingsFilename);
   8756                 }
   8757                 XmlPullParser parser = Xml.newPullParser();
   8758                 parser.setInput(str, null);
   8759 
   8760                 int type;
   8761                 while ((type=parser.next()) != XmlPullParser.START_TAG
   8762                            && type != XmlPullParser.END_DOCUMENT) {
   8763                     ;
   8764                 }
   8765 
   8766                 if (type != XmlPullParser.START_TAG) {
   8767                     mReadMessages.append("No start tag found in settings file\n");
   8768                     Slog.e(TAG, "No start tag found in package manager settings");
   8769                     return false;
   8770                 }
   8771 
   8772                 int outerDepth = parser.getDepth();
   8773                 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   8774                        && (type != XmlPullParser.END_TAG
   8775                                || parser.getDepth() > outerDepth)) {
   8776                     if (type == XmlPullParser.END_TAG
   8777                             || type == XmlPullParser.TEXT) {
   8778                         continue;
   8779                     }
   8780 
   8781                     String tagName = parser.getName();
   8782                     if (tagName.equals("package")) {
   8783                         readPackageLP(parser);
   8784                     } else if (tagName.equals("permissions")) {
   8785                         readPermissionsLP(mPermissions, parser);
   8786                     } else if (tagName.equals("permission-trees")) {
   8787                         readPermissionsLP(mPermissionTrees, parser);
   8788                     } else if (tagName.equals("shared-user")) {
   8789                         readSharedUserLP(parser);
   8790                     } else if (tagName.equals("preferred-packages")) {
   8791                         // no longer used.
   8792                     } else if (tagName.equals("preferred-activities")) {
   8793                         readPreferredActivitiesLP(parser);
   8794                     } else if(tagName.equals("updated-package")) {
   8795                         readDisabledSysPackageLP(parser);
   8796                     } else if (tagName.equals("cleaning-package")) {
   8797                         String name = parser.getAttributeValue(null, "name");
   8798                         if (name != null) {
   8799                             mPackagesToBeCleaned.add(name);
   8800                         }
   8801                     } else if (tagName.equals("renamed-package")) {
   8802                         String nname = parser.getAttributeValue(null, "new");
   8803                         String oname = parser.getAttributeValue(null, "old");
   8804                         if (nname != null && oname != null) {
   8805                             mRenamedPackages.put(nname, oname);
   8806                         }
   8807                     } else if (tagName.equals("last-platform-version")) {
   8808                         mInternalSdkPlatform = mExternalSdkPlatform = 0;
   8809                         try {
   8810                             String internal = parser.getAttributeValue(null, "internal");
   8811                             if (internal != null) {
   8812                                 mInternalSdkPlatform = Integer.parseInt(internal);
   8813                             }
   8814                             String external = parser.getAttributeValue(null, "external");
   8815                             if (external != null) {
   8816                                 mExternalSdkPlatform = Integer.parseInt(external);
   8817                             }
   8818                         } catch (NumberFormatException e) {
   8819                         }
   8820                     } else {
   8821                         Slog.w(TAG, "Unknown element under <packages>: "
   8822                               + parser.getName());
   8823                         XmlUtils.skipCurrentTag(parser);
   8824                     }
   8825                 }
   8826 
   8827                 str.close();
   8828 
   8829             } catch(XmlPullParserException e) {
   8830                 mReadMessages.append("Error reading: " + e.toString());
   8831                 Slog.e(TAG, "Error reading package manager settings", e);
   8832 
   8833             } catch(java.io.IOException e) {
   8834                 mReadMessages.append("Error reading: " + e.toString());
   8835                 Slog.e(TAG, "Error reading package manager settings", e);
   8836 
   8837             }
   8838 
   8839             int N = mPendingPackages.size();
   8840             for (int i=0; i<N; i++) {
   8841                 final PendingPackage pp = mPendingPackages.get(i);
   8842                 Object idObj = getUserIdLP(pp.sharedId);
   8843                 if (idObj != null && idObj instanceof SharedUserSetting) {
   8844                     PackageSetting p = getPackageLP(pp.name, null, pp.realName,
   8845                             (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
   8846                             pp.versionCode, pp.pkgFlags, true, true);
   8847                     if (p == null) {
   8848                         Slog.w(TAG, "Unable to create application package for "
   8849                                 + pp.name);
   8850                         continue;
   8851                     }
   8852                     p.copyFrom(pp);
   8853                 } else if (idObj != null) {
   8854                     String msg = "Bad package setting: package " + pp.name
   8855                             + " has shared uid " + pp.sharedId
   8856                             + " that is not a shared uid\n";
   8857                     mReadMessages.append(msg);
   8858                     Slog.e(TAG, msg);
   8859                 } else {
   8860                     String msg = "Bad package setting: package " + pp.name
   8861                             + " has shared uid " + pp.sharedId
   8862                             + " that is not defined\n";
   8863                     mReadMessages.append(msg);
   8864                     Slog.e(TAG, msg);
   8865                 }
   8866             }
   8867             mPendingPackages.clear();
   8868 
   8869             mReadMessages.append("Read completed successfully: "
   8870                     + mPackages.size() + " packages, "
   8871                     + mSharedUsers.size() + " shared uids\n");
   8872 
   8873             return true;
   8874         }
   8875 
   8876         private int readInt(XmlPullParser parser, String ns, String name,
   8877                 int defValue) {
   8878             String v = parser.getAttributeValue(ns, name);
   8879             try {
   8880                 if (v == null) {
   8881                     return defValue;
   8882                 }
   8883                 return Integer.parseInt(v);
   8884             } catch (NumberFormatException e) {
   8885                 reportSettingsProblem(Log.WARN,
   8886                         "Error in package manager settings: attribute " +
   8887                         name + " has bad integer value " + v + " at "
   8888                         + parser.getPositionDescription());
   8889             }
   8890             return defValue;
   8891         }
   8892 
   8893         private void readPermissionsLP(HashMap<String, BasePermission> out,
   8894                 XmlPullParser parser)
   8895                 throws IOException, XmlPullParserException {
   8896             int outerDepth = parser.getDepth();
   8897             int type;
   8898             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   8899                    && (type != XmlPullParser.END_TAG
   8900                            || parser.getDepth() > outerDepth)) {
   8901                 if (type == XmlPullParser.END_TAG
   8902                         || type == XmlPullParser.TEXT) {
   8903                     continue;
   8904                 }
   8905 
   8906                 String tagName = parser.getName();
   8907                 if (tagName.equals("item")) {
   8908                     String name = parser.getAttributeValue(null, "name");
   8909                     String sourcePackage = parser.getAttributeValue(null, "package");
   8910                     String ptype = parser.getAttributeValue(null, "type");
   8911                     if (name != null && sourcePackage != null) {
   8912                         boolean dynamic = "dynamic".equals(ptype);
   8913                         BasePermission bp = new BasePermission(name, sourcePackage,
   8914                                 dynamic
   8915                                 ? BasePermission.TYPE_DYNAMIC
   8916                                 : BasePermission.TYPE_NORMAL);
   8917                         bp.protectionLevel = readInt(parser, null, "protection",
   8918                                 PermissionInfo.PROTECTION_NORMAL);
   8919                         if (dynamic) {
   8920                             PermissionInfo pi = new PermissionInfo();
   8921                             pi.packageName = sourcePackage.intern();
   8922                             pi.name = name.intern();
   8923                             pi.icon = readInt(parser, null, "icon", 0);
   8924                             pi.nonLocalizedLabel = parser.getAttributeValue(
   8925                                     null, "label");
   8926                             pi.protectionLevel = bp.protectionLevel;
   8927                             bp.pendingInfo = pi;
   8928                         }
   8929                         out.put(bp.name, bp);
   8930                     } else {
   8931                         reportSettingsProblem(Log.WARN,
   8932                                 "Error in package manager settings: permissions has"
   8933                                 + " no name at " + parser.getPositionDescription());
   8934                     }
   8935                 } else {
   8936                     reportSettingsProblem(Log.WARN,
   8937                             "Unknown element reading permissions: "
   8938                             + parser.getName() + " at "
   8939                             + parser.getPositionDescription());
   8940                 }
   8941                 XmlUtils.skipCurrentTag(parser);
   8942             }
   8943         }
   8944 
   8945         private void readDisabledSysPackageLP(XmlPullParser parser)
   8946                 throws XmlPullParserException, IOException {
   8947             String name = parser.getAttributeValue(null, "name");
   8948             String realName = parser.getAttributeValue(null, "realName");
   8949             String codePathStr = parser.getAttributeValue(null, "codePath");
   8950             String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
   8951             if (resourcePathStr == null) {
   8952                 resourcePathStr = codePathStr;
   8953             }
   8954             String version = parser.getAttributeValue(null, "version");
   8955             int versionCode = 0;
   8956             if (version != null) {
   8957                 try {
   8958                     versionCode = Integer.parseInt(version);
   8959                 } catch (NumberFormatException e) {
   8960                 }
   8961             }
   8962 
   8963             int pkgFlags = 0;
   8964             pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
   8965             PackageSetting ps = new PackageSetting(name, realName,
   8966                     new File(codePathStr),
   8967                     new File(resourcePathStr), versionCode, pkgFlags);
   8968             String timeStampStr = parser.getAttributeValue(null, "ts");
   8969             if (timeStampStr != null) {
   8970                 try {
   8971                     long timeStamp = Long.parseLong(timeStampStr);
   8972                     ps.setTimeStamp(timeStamp, timeStampStr);
   8973                 } catch (NumberFormatException e) {
   8974                 }
   8975             }
   8976             String idStr = parser.getAttributeValue(null, "userId");
   8977             ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
   8978             if(ps.userId <= 0) {
   8979                 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
   8980                 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
   8981             }
   8982             int outerDepth = parser.getDepth();
   8983             int type;
   8984             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   8985                    && (type != XmlPullParser.END_TAG
   8986                            || parser.getDepth() > outerDepth)) {
   8987                 if (type == XmlPullParser.END_TAG
   8988                         || type == XmlPullParser.TEXT) {
   8989                     continue;
   8990                 }
   8991 
   8992                 String tagName = parser.getName();
   8993                 if (tagName.equals("perms")) {
   8994                     readGrantedPermissionsLP(parser,
   8995                             ps.grantedPermissions);
   8996                 } else {
   8997                     reportSettingsProblem(Log.WARN,
   8998                             "Unknown element under <updated-package>: "
   8999                             + parser.getName());
   9000                     XmlUtils.skipCurrentTag(parser);
   9001                 }
   9002             }
   9003             mDisabledSysPackages.put(name, ps);
   9004         }
   9005 
   9006         private void readPackageLP(XmlPullParser parser)
   9007                 throws XmlPullParserException, IOException {
   9008             String name = null;
   9009             String realName = null;
   9010             String idStr = null;
   9011             String sharedIdStr = null;
   9012             String codePathStr = null;
   9013             String resourcePathStr = null;
   9014             String systemStr = null;
   9015             String installerPackageName = null;
   9016             String uidError = null;
   9017             int pkgFlags = 0;
   9018             String timeStampStr;
   9019             long timeStamp = 0;
   9020             PackageSettingBase packageSetting = null;
   9021             String version = null;
   9022             int versionCode = 0;
   9023             try {
   9024                 name = parser.getAttributeValue(null, "name");
   9025                 realName = parser.getAttributeValue(null, "realName");
   9026                 idStr = parser.getAttributeValue(null, "userId");
   9027                 uidError = parser.getAttributeValue(null, "uidError");
   9028                 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
   9029                 codePathStr = parser.getAttributeValue(null, "codePath");
   9030                 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
   9031                 version = parser.getAttributeValue(null, "version");
   9032                 if (version != null) {
   9033                     try {
   9034                         versionCode = Integer.parseInt(version);
   9035                     } catch (NumberFormatException e) {
   9036                     }
   9037                 }
   9038                 installerPackageName = parser.getAttributeValue(null, "installer");
   9039 
   9040                 systemStr = parser.getAttributeValue(null, "flags");
   9041                 if (systemStr != null) {
   9042                     try {
   9043                         pkgFlags = Integer.parseInt(systemStr);
   9044                     } catch (NumberFormatException e) {
   9045                     }
   9046                 } else {
   9047                     // For backward compatibility
   9048                     systemStr = parser.getAttributeValue(null, "system");
   9049                     if (systemStr != null) {
   9050                         pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
   9051                     } else {
   9052                         // Old settings that don't specify system...  just treat
   9053                         // them as system, good enough.
   9054                         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
   9055                     }
   9056                 }
   9057                 timeStampStr = parser.getAttributeValue(null, "ts");
   9058                 if (timeStampStr != null) {
   9059                     try {
   9060                         timeStamp = Long.parseLong(timeStampStr);
   9061                     } catch (NumberFormatException e) {
   9062                     }
   9063                 }
   9064                 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
   9065                         + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
   9066                 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
   9067                 if (resourcePathStr == null) {
   9068                     resourcePathStr = codePathStr;
   9069                 }
   9070                 if (realName != null) {
   9071                     realName = realName.intern();
   9072                 }
   9073                 if (name == null) {
   9074                     reportSettingsProblem(Log.WARN,
   9075                             "Error in package manager settings: <package> has no name at "
   9076                             + parser.getPositionDescription());
   9077                 } else if (codePathStr == null) {
   9078                     reportSettingsProblem(Log.WARN,
   9079                             "Error in package manager settings: <package> has no codePath at "
   9080                             + parser.getPositionDescription());
   9081                 } else if (userId > 0) {
   9082                     packageSetting = addPackageLP(name.intern(), realName,
   9083                             new File(codePathStr), new File(resourcePathStr),
   9084                             userId, versionCode, pkgFlags);
   9085                     if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
   9086                             + ": userId=" + userId + " pkg=" + packageSetting);
   9087                     if (packageSetting == null) {
   9088                         reportSettingsProblem(Log.ERROR,
   9089                                 "Failure adding uid " + userId
   9090                                 + " while parsing settings at "
   9091                                 + parser.getPositionDescription());
   9092                     } else {
   9093                         packageSetting.setTimeStamp(timeStamp, timeStampStr);
   9094                     }
   9095                 } else if (sharedIdStr != null) {
   9096                     userId = sharedIdStr != null
   9097                             ? Integer.parseInt(sharedIdStr) : 0;
   9098                     if (userId > 0) {
   9099                         packageSetting = new PendingPackage(name.intern(), realName,
   9100                                 new File(codePathStr), new File(resourcePathStr),
   9101                                 userId, versionCode, pkgFlags);
   9102                         packageSetting.setTimeStamp(timeStamp, timeStampStr);
   9103                         mPendingPackages.add((PendingPackage) packageSetting);
   9104                         if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
   9105                                 + ": sharedUserId=" + userId + " pkg="
   9106                                 + packageSetting);
   9107                     } else {
   9108                         reportSettingsProblem(Log.WARN,
   9109                                 "Error in package manager settings: package "
   9110                                 + name + " has bad sharedId " + sharedIdStr
   9111                                 + " at " + parser.getPositionDescription());
   9112                     }
   9113                 } else {
   9114                     reportSettingsProblem(Log.WARN,
   9115                             "Error in package manager settings: package "
   9116                             + name + " has bad userId " + idStr + " at "
   9117                             + parser.getPositionDescription());
   9118                 }
   9119             } catch (NumberFormatException e) {
   9120                 reportSettingsProblem(Log.WARN,
   9121                         "Error in package manager settings: package "
   9122                         + name + " has bad userId " + idStr + " at "
   9123                         + parser.getPositionDescription());
   9124             }
   9125             if (packageSetting != null) {
   9126                 packageSetting.uidError = "true".equals(uidError);
   9127                 packageSetting.installerPackageName = installerPackageName;
   9128                 final String enabledStr = parser.getAttributeValue(null, "enabled");
   9129                 if (enabledStr != null) {
   9130                     if (enabledStr.equalsIgnoreCase("true")) {
   9131                         packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
   9132                     } else if (enabledStr.equalsIgnoreCase("false")) {
   9133                         packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
   9134                     } else if (enabledStr.equalsIgnoreCase("default")) {
   9135                         packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
   9136                     } else {
   9137                         reportSettingsProblem(Log.WARN,
   9138                                 "Error in package manager settings: package "
   9139                                 + name + " has bad enabled value: " + idStr
   9140                                 + " at " + parser.getPositionDescription());
   9141                     }
   9142                 } else {
   9143                     packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
   9144                 }
   9145                 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
   9146                 if (installStatusStr != null) {
   9147                     if (installStatusStr.equalsIgnoreCase("false")) {
   9148                         packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
   9149                     } else {
   9150                         packageSetting.installStatus = PKG_INSTALL_COMPLETE;
   9151                     }
   9152                 }
   9153 
   9154                 int outerDepth = parser.getDepth();
   9155                 int type;
   9156                 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   9157                        && (type != XmlPullParser.END_TAG
   9158                                || parser.getDepth() > outerDepth)) {
   9159                     if (type == XmlPullParser.END_TAG
   9160                             || type == XmlPullParser.TEXT) {
   9161                         continue;
   9162                     }
   9163 
   9164                     String tagName = parser.getName();
   9165                     if (tagName.equals("disabled-components")) {
   9166                         readDisabledComponentsLP(packageSetting, parser);
   9167                     } else if (tagName.equals("enabled-components")) {
   9168                         readEnabledComponentsLP(packageSetting, parser);
   9169                     } else if (tagName.equals("sigs")) {
   9170                         packageSetting.signatures.readXml(parser, mPastSignatures);
   9171                     } else if (tagName.equals("perms")) {
   9172                         readGrantedPermissionsLP(parser,
   9173                                 packageSetting.grantedPermissions);
   9174                         packageSetting.permissionsFixed = true;
   9175                     } else {
   9176                         reportSettingsProblem(Log.WARN,
   9177                                 "Unknown element under <package>: "
   9178                                 + parser.getName());
   9179                         XmlUtils.skipCurrentTag(parser);
   9180                     }
   9181                 }
   9182             } else {
   9183                 XmlUtils.skipCurrentTag(parser);
   9184             }
   9185         }
   9186 
   9187         private void readDisabledComponentsLP(PackageSettingBase packageSetting,
   9188                                                   XmlPullParser parser)
   9189                 throws IOException, XmlPullParserException {
   9190             int outerDepth = parser.getDepth();
   9191             int type;
   9192             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   9193                    && (type != XmlPullParser.END_TAG
   9194                            || parser.getDepth() > outerDepth)) {
   9195                 if (type == XmlPullParser.END_TAG
   9196                         || type == XmlPullParser.TEXT) {
   9197                     continue;
   9198                 }
   9199 
   9200                 String tagName = parser.getName();
   9201                 if (tagName.equals("item")) {
   9202                     String name = parser.getAttributeValue(null, "name");
   9203                     if (name != null) {
   9204                         packageSetting.disabledComponents.add(name.intern());
   9205                     } else {
   9206                         reportSettingsProblem(Log.WARN,
   9207                                 "Error in package manager settings: <disabled-components> has"
   9208                                 + " no name at " + parser.getPositionDescription());
   9209                     }
   9210                 } else {
   9211                     reportSettingsProblem(Log.WARN,
   9212                             "Unknown element under <disabled-components>: "
   9213                             + parser.getName());
   9214                 }
   9215                 XmlUtils.skipCurrentTag(parser);
   9216             }
   9217         }
   9218 
   9219         private void readEnabledComponentsLP(PackageSettingBase packageSetting,
   9220                                                   XmlPullParser parser)
   9221                 throws IOException, XmlPullParserException {
   9222             int outerDepth = parser.getDepth();
   9223             int type;
   9224             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   9225                    && (type != XmlPullParser.END_TAG
   9226                            || parser.getDepth() > outerDepth)) {
   9227                 if (type == XmlPullParser.END_TAG
   9228                         || type == XmlPullParser.TEXT) {
   9229                     continue;
   9230                 }
   9231 
   9232                 String tagName = parser.getName();
   9233                 if (tagName.equals("item")) {
   9234                     String name = parser.getAttributeValue(null, "name");
   9235                     if (name != null) {
   9236                         packageSetting.enabledComponents.add(name.intern());
   9237                     } else {
   9238                         reportSettingsProblem(Log.WARN,
   9239                                 "Error in package manager settings: <enabled-components> has"
   9240                                    + " no name at " + parser.getPositionDescription());
   9241                     }
   9242                 } else {
   9243                     reportSettingsProblem(Log.WARN,
   9244                             "Unknown element under <enabled-components>: "
   9245                             + parser.getName());
   9246                 }
   9247                 XmlUtils.skipCurrentTag(parser);
   9248             }
   9249         }
   9250 
   9251         private void readSharedUserLP(XmlPullParser parser)
   9252                 throws XmlPullParserException, IOException {
   9253             String name = null;
   9254             String idStr = null;
   9255             int pkgFlags = 0;
   9256             SharedUserSetting su = null;
   9257             try {
   9258                 name = parser.getAttributeValue(null, "name");
   9259                 idStr = parser.getAttributeValue(null, "userId");
   9260                 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
   9261                 if ("true".equals(parser.getAttributeValue(null, "system"))) {
   9262                     pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
   9263                 }
   9264                 if (name == null) {
   9265                     reportSettingsProblem(Log.WARN,
   9266                             "Error in package manager settings: <shared-user> has no name at "
   9267                             + parser.getPositionDescription());
   9268                 } else if (userId == 0) {
   9269                     reportSettingsProblem(Log.WARN,
   9270                             "Error in package manager settings: shared-user "
   9271                             + name + " has bad userId " + idStr + " at "
   9272                             + parser.getPositionDescription());
   9273                 } else {
   9274                     if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
   9275                         reportSettingsProblem(Log.ERROR,
   9276                                 "Occurred while parsing settings at "
   9277                                 + parser.getPositionDescription());
   9278                     }
   9279                 }
   9280             } catch (NumberFormatException e) {
   9281                 reportSettingsProblem(Log.WARN,
   9282                         "Error in package manager settings: package "
   9283                         + name + " has bad userId " + idStr + " at "
   9284                         + parser.getPositionDescription());
   9285             };
   9286 
   9287             if (su != null) {
   9288                 int outerDepth = parser.getDepth();
   9289                 int type;
   9290                 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   9291                        && (type != XmlPullParser.END_TAG
   9292                                || parser.getDepth() > outerDepth)) {
   9293                     if (type == XmlPullParser.END_TAG
   9294                             || type == XmlPullParser.TEXT) {
   9295                         continue;
   9296                     }
   9297 
   9298                     String tagName = parser.getName();
   9299                     if (tagName.equals("sigs")) {
   9300                         su.signatures.readXml(parser, mPastSignatures);
   9301                     } else if (tagName.equals("perms")) {
   9302                         readGrantedPermissionsLP(parser, su.grantedPermissions);
   9303                     } else {
   9304                         reportSettingsProblem(Log.WARN,
   9305                                 "Unknown element under <shared-user>: "
   9306                                 + parser.getName());
   9307                         XmlUtils.skipCurrentTag(parser);
   9308                     }
   9309                 }
   9310 
   9311             } else {
   9312                 XmlUtils.skipCurrentTag(parser);
   9313             }
   9314         }
   9315 
   9316         private void readGrantedPermissionsLP(XmlPullParser parser,
   9317                 HashSet<String> outPerms) throws IOException, XmlPullParserException {
   9318             int outerDepth = parser.getDepth();
   9319             int type;
   9320             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   9321                    && (type != XmlPullParser.END_TAG
   9322                            || parser.getDepth() > outerDepth)) {
   9323                 if (type == XmlPullParser.END_TAG
   9324                         || type == XmlPullParser.TEXT) {
   9325                     continue;
   9326                 }
   9327 
   9328                 String tagName = parser.getName();
   9329                 if (tagName.equals("item")) {
   9330                     String name = parser.getAttributeValue(null, "name");
   9331                     if (name != null) {
   9332                         outPerms.add(name.intern());
   9333                     } else {
   9334                         reportSettingsProblem(Log.WARN,
   9335                                 "Error in package manager settings: <perms> has"
   9336                                    + " no name at " + parser.getPositionDescription());
   9337                     }
   9338                 } else {
   9339                     reportSettingsProblem(Log.WARN,
   9340                             "Unknown element under <perms>: "
   9341                             + parser.getName());
   9342                 }
   9343                 XmlUtils.skipCurrentTag(parser);
   9344             }
   9345         }
   9346 
   9347         private void readPreferredActivitiesLP(XmlPullParser parser)
   9348                 throws XmlPullParserException, IOException {
   9349             int outerDepth = parser.getDepth();
   9350             int type;
   9351             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   9352                    && (type != XmlPullParser.END_TAG
   9353                            || parser.getDepth() > outerDepth)) {
   9354                 if (type == XmlPullParser.END_TAG
   9355                         || type == XmlPullParser.TEXT) {
   9356                     continue;
   9357                 }
   9358 
   9359                 String tagName = parser.getName();
   9360                 if (tagName.equals("item")) {
   9361                     PreferredActivity pa = new PreferredActivity(parser);
   9362                     if (pa.mParseError == null) {
   9363                         mPreferredActivities.addFilter(pa);
   9364                     } else {
   9365                         reportSettingsProblem(Log.WARN,
   9366                                 "Error in package manager settings: <preferred-activity> "
   9367                                 + pa.mParseError + " at "
   9368                                 + parser.getPositionDescription());
   9369                     }
   9370                 } else {
   9371                     reportSettingsProblem(Log.WARN,
   9372                             "Unknown element under <preferred-activities>: "
   9373                             + parser.getName());
   9374                     XmlUtils.skipCurrentTag(parser);
   9375                 }
   9376             }
   9377         }
   9378 
   9379         // Returns -1 if we could not find an available UserId to assign
   9380         private int newUserIdLP(Object obj) {
   9381             // Let's be stupidly inefficient for now...
   9382             final int N = mUserIds.size();
   9383             for (int i=0; i<N; i++) {
   9384                 if (mUserIds.get(i) == null) {
   9385                     mUserIds.set(i, obj);
   9386                     return FIRST_APPLICATION_UID + i;
   9387                 }
   9388             }
   9389 
   9390             // None left?
   9391             if (N >= MAX_APPLICATION_UIDS) {
   9392                 return -1;
   9393             }
   9394 
   9395             mUserIds.add(obj);
   9396             return FIRST_APPLICATION_UID + N;
   9397         }
   9398 
   9399         public PackageSetting getDisabledSystemPkg(String name) {
   9400             synchronized(mPackages) {
   9401                 PackageSetting ps = mDisabledSysPackages.get(name);
   9402                 return ps;
   9403             }
   9404         }
   9405 
   9406         boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
   9407             final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
   9408             if (Config.LOGV) {
   9409                 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
   9410                            + " componentName = " + componentInfo.name);
   9411                 Log.v(TAG, "enabledComponents: "
   9412                            + Arrays.toString(packageSettings.enabledComponents.toArray()));
   9413                 Log.v(TAG, "disabledComponents: "
   9414                            + Arrays.toString(packageSettings.disabledComponents.toArray()));
   9415             }
   9416             if (packageSettings == null) {
   9417                 if (false) {
   9418                     Log.w(TAG, "WAITING FOR DEBUGGER");
   9419                     Debug.waitForDebugger();
   9420                     Log.i(TAG, "We will crash!");
   9421                 }
   9422             }
   9423             return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
   9424                    || ((componentInfo.enabled
   9425                         && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
   9426                             || (componentInfo.applicationInfo.enabled
   9427                                 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
   9428                         && !packageSettings.disabledComponents.contains(componentInfo.name))
   9429                        || packageSettings.enabledComponents.contains(componentInfo.name));
   9430         }
   9431     }
   9432 
   9433     // ------- apps on sdcard specific code -------
   9434     static final boolean DEBUG_SD_INSTALL = false;
   9435     final private String mSdEncryptKey = "AppsOnSD";
   9436     final private String mSdEncryptAlg = "AES";
   9437     private boolean mMediaMounted = false;
   9438     private static final int MAX_CONTAINERS = 250;
   9439 
   9440     private String getEncryptKey() {
   9441         try {
   9442             String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
   9443             if (sdEncKey == null) {
   9444                 sdEncKey = SystemKeyStore.getInstance().
   9445                         generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
   9446                 if (sdEncKey == null) {
   9447                     Slog.e(TAG, "Failed to create encryption keys");
   9448                     return null;
   9449                 }
   9450             }
   9451             return sdEncKey;
   9452         } catch (NoSuchAlgorithmException nsae) {
   9453             Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
   9454             return null;
   9455         }
   9456     }
   9457 
   9458    static String getTempContainerId() {
   9459        String prefix = "smdl2tmp";
   9460        int tmpIdx = 1;
   9461        String list[] = PackageHelper.getSecureContainerList();
   9462        if (list != null) {
   9463            int idx = 0;
   9464            int idList[] = new int[MAX_CONTAINERS];
   9465            boolean neverFound = true;
   9466            for (String name : list) {
   9467                // Ignore null entries
   9468                if (name == null) {
   9469                    continue;
   9470                }
   9471                int sidx = name.indexOf(prefix);
   9472                if (sidx == -1) {
   9473                    // Not a temp file. just ignore
   9474                    continue;
   9475                }
   9476                String subStr = name.substring(sidx + prefix.length());
   9477                idList[idx] = -1;
   9478                if (subStr != null) {
   9479                    try {
   9480                        int cid = Integer.parseInt(subStr);
   9481                        idList[idx++] = cid;
   9482                        neverFound = false;
   9483                    } catch (NumberFormatException e) {
   9484                    }
   9485                }
   9486            }
   9487            if (!neverFound) {
   9488                // Sort idList
   9489                Arrays.sort(idList);
   9490                for (int j = 1; j <= idList.length; j++) {
   9491                    if (idList[j-1] != j) {
   9492                        tmpIdx = j;
   9493                        break;
   9494                    }
   9495                }
   9496            }
   9497        }
   9498        return prefix + tmpIdx;
   9499    }
   9500 
   9501    /*
   9502     * Update media status on PackageManager.
   9503     */
   9504    public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
   9505        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
   9506            throw new SecurityException("Media status can only be updated by the system");
   9507        }
   9508        synchronized (mPackages) {
   9509            Log.i(TAG, "Updating external media status from " +
   9510                    (mMediaMounted ? "mounted" : "unmounted") + " to " +
   9511                    (mediaStatus ? "mounted" : "unmounted"));
   9512            if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
   9513                    mediaStatus+", mMediaMounted=" + mMediaMounted);
   9514            if (mediaStatus == mMediaMounted) {
   9515                Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
   9516                        reportStatus ? 1 : 0, -1);
   9517                mHandler.sendMessage(msg);
   9518                return;
   9519            }
   9520            mMediaMounted = mediaStatus;
   9521        }
   9522        // Queue up an async operation since the package installation may take a little while.
   9523        mHandler.post(new Runnable() {
   9524            public void run() {
   9525                mHandler.removeCallbacks(this);
   9526                updateExternalMediaStatusInner(mediaStatus, reportStatus);
   9527            }
   9528        });
   9529    }
   9530 
   9531    /*
   9532     * Collect information of applications on external media, map them
   9533     * against existing containers and update information based on current
   9534     * mount status. Please note that we always have to report status
   9535     * if reportStatus has been set to true especially when unloading packages.
   9536     */
   9537    private void updateExternalMediaStatusInner(boolean mediaStatus,
   9538            boolean reportStatus) {
   9539        // Collection of uids
   9540        int uidArr[] = null;
   9541        // Collection of stale containers
   9542        HashSet<String> removeCids = new HashSet<String>();
   9543        // Collection of packages on external media with valid containers.
   9544        HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
   9545        // Get list of secure containers.
   9546        final String list[] = PackageHelper.getSecureContainerList();
   9547        if (list == null || list.length == 0) {
   9548            Log.i(TAG, "No secure containers on sdcard");
   9549        } else {
   9550            // Process list of secure containers and categorize them
   9551            // as active or stale based on their package internal state.
   9552            int uidList[] = new int[list.length];
   9553            int num = 0;
   9554            synchronized (mPackages) {
   9555                for (String cid : list) {
   9556                    SdInstallArgs args = new SdInstallArgs(cid);
   9557                    if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
   9558                    String pkgName = args.getPackageName();
   9559                    if (pkgName == null) {
   9560                        if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
   9561                        removeCids.add(cid);
   9562                        continue;
   9563                    }
   9564                    if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
   9565                    PackageSetting ps = mSettings.mPackages.get(pkgName);
   9566                    // The package status is changed only if the code path
   9567                    // matches between settings and the container id.
   9568                    if (ps != null && ps.codePathString != null &&
   9569                            ps.codePathString.equals(args.getCodePath())) {
   9570                        if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid +
   9571                                " corresponds to pkg : " + pkgName +
   9572                                " at code path: " + ps.codePathString);
   9573                        // We do have a valid package installed on sdcard
   9574                        processCids.put(args, ps.codePathString);
   9575                        int uid = ps.userId;
   9576                        if (uid != -1) {
   9577                            uidList[num++] = uid;
   9578                        }
   9579                    } else {
   9580                        // Stale container on sdcard. Just delete
   9581                        if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
   9582                        removeCids.add(cid);
   9583                    }
   9584                }
   9585            }
   9586 
   9587            if (num > 0) {
   9588                // Sort uid list
   9589                Arrays.sort(uidList, 0, num);
   9590                // Throw away duplicates
   9591                uidArr = new int[num];
   9592                uidArr[0] = uidList[0];
   9593                int di = 0;
   9594                for (int i = 1; i < num; i++) {
   9595                    if (uidList[i-1] != uidList[i]) {
   9596                        uidArr[di++] = uidList[i];
   9597                    }
   9598                }
   9599            }
   9600        }
   9601        // Process packages with valid entries.
   9602        if (mediaStatus) {
   9603            if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
   9604            loadMediaPackages(processCids, uidArr, removeCids);
   9605            startCleaningPackages();
   9606        } else {
   9607            if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
   9608            unloadMediaPackages(processCids, uidArr, reportStatus);
   9609        }
   9610    }
   9611 
   9612    private void sendResourcesChangedBroadcast(boolean mediaStatus,
   9613            ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
   9614        int size = pkgList.size();
   9615        if (size > 0) {
   9616            // Send broadcasts here
   9617            Bundle extras = new Bundle();
   9618            extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
   9619                    pkgList.toArray(new String[size]));
   9620            if (uidArr != null) {
   9621                extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
   9622            }
   9623            String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
   9624                    : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
   9625            sendPackageBroadcast(action, null, extras, finishedReceiver);
   9626        }
   9627    }
   9628 
   9629    /*
   9630     * Look at potentially valid container ids from processCids
   9631     * If package information doesn't match the one on record
   9632     * or package scanning fails, the cid is added to list of
   9633     * removeCids. We currently don't delete stale containers.
   9634     */
   9635    private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
   9636            int uidArr[], HashSet<String> removeCids) {
   9637        ArrayList<String> pkgList = new ArrayList<String>();
   9638        Set<SdInstallArgs> keys = processCids.keySet();
   9639        boolean doGc = false;
   9640        for (SdInstallArgs args : keys) {
   9641            String codePath = processCids.get(args);
   9642            if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : "
   9643                    + args.cid);
   9644            int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
   9645            try {
   9646                // Make sure there are no container errors first.
   9647                if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED)
   9648                        != PackageManager.INSTALL_SUCCEEDED) {
   9649                    Slog.e(TAG, "Failed to mount cid : " + args.cid +
   9650                    " when installing from sdcard");
   9651                    continue;
   9652                }
   9653                // Check code path here.
   9654                if (codePath == null || !codePath.equals(args.getCodePath())) {
   9655                    Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+
   9656                            " does not match one in settings " + codePath);
   9657                    continue;
   9658                }
   9659                // Parse package
   9660                int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
   9661                doGc = true;
   9662                synchronized (mInstallLock) {
   9663                    final PackageParser.Package pkg =  scanPackageLI(new File(codePath),
   9664                            parseFlags, 0);
   9665                    // Scan the package
   9666                    if (pkg != null) {
   9667                        synchronized (mPackages) {
   9668                            retCode = PackageManager.INSTALL_SUCCEEDED;
   9669                            pkgList.add(pkg.packageName);
   9670                            // Post process args
   9671                            args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
   9672                        }
   9673                    } else {
   9674                        Slog.i(TAG, "Failed to install pkg from  " +
   9675                                codePath + " from sdcard");
   9676                    }
   9677                }
   9678 
   9679            } finally {
   9680                if (retCode != PackageManager.INSTALL_SUCCEEDED) {
   9681                    // Don't destroy container here. Wait till gc clears things up.
   9682                    removeCids.add(args.cid);
   9683                }
   9684            }
   9685        }
   9686        synchronized (mPackages) {
   9687            // If the platform SDK has changed since the last time we booted,
   9688            // we need to re-grant app permission to catch any new ones that
   9689            // appear.  This is really a hack, and means that apps can in some
   9690            // cases get permissions that the user didn't initially explicitly
   9691            // allow...  it would be nice to have some better way to handle
   9692            // this situation.
   9693            final boolean regrantPermissions = mSettings.mExternalSdkPlatform
   9694                    != mSdkVersion;
   9695            if (regrantPermissions) Slog.i(TAG, "Platform changed from "
   9696                    + mSettings.mExternalSdkPlatform + " to " + mSdkVersion
   9697                    + "; regranting permissions for external storage");
   9698            mSettings.mExternalSdkPlatform = mSdkVersion;
   9699 
   9700            // Make sure group IDs have been assigned, and any permission
   9701            // changes in other apps are accounted for
   9702            updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions);
   9703            // Persist settings
   9704            mSettings.writeLP();
   9705        }
   9706        // Send a broadcast to let everyone know we are done processing
   9707        if (pkgList.size() > 0) {
   9708            sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
   9709        }
   9710        // Force gc to avoid any stale parser references that we might have.
   9711        if (doGc) {
   9712            Runtime.getRuntime().gc();
   9713        }
   9714        // List stale containers.
   9715        if (removeCids != null) {
   9716            for (String cid : removeCids) {
   9717                Log.w(TAG, "Container " + cid + " is stale");
   9718            }
   9719        }
   9720    }
   9721 
   9722    /*
   9723     * Utility method to unload a list of specified containers
   9724     */
   9725    private void unloadAllContainers(Set<SdInstallArgs> cidArgs) {
   9726        // Just unmount all valid containers.
   9727        for (SdInstallArgs arg : cidArgs) {
   9728            synchronized (mInstallLock) {
   9729                arg.doPostDeleteLI(false);
   9730            }
   9731        }
   9732    }
   9733 
   9734    /*
   9735     * Unload packages mounted on external media. This involves deleting
   9736     * package data from internal structures, sending broadcasts about
   9737     * diabled packages, gc'ing to free up references, unmounting all
   9738     * secure containers corresponding to packages on external media, and
   9739     * posting a UPDATED_MEDIA_STATUS message if status has been requested.
   9740     * Please note that we always have to post this message if status has
   9741     * been requested no matter what.
   9742     */
   9743    private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
   9744            int uidArr[], final boolean reportStatus) {
   9745        if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
   9746        ArrayList<String> pkgList = new ArrayList<String>();
   9747        ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
   9748        final Set<SdInstallArgs> keys = processCids.keySet();
   9749        for (SdInstallArgs args : keys) {
   9750            String cid = args.cid;
   9751            String pkgName = args.getPackageName();
   9752            if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
   9753            // Delete package internally
   9754            PackageRemovedInfo outInfo = new PackageRemovedInfo();
   9755            synchronized (mInstallLock) {
   9756                boolean res = deletePackageLI(pkgName, false,
   9757                        PackageManager.DONT_DELETE_DATA, outInfo);
   9758                if (res) {
   9759                    pkgList.add(pkgName);
   9760                } else {
   9761                    Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
   9762                    failedList.add(args);
   9763                }
   9764            }
   9765        }
   9766        // We have to absolutely send UPDATED_MEDIA_STATUS only
   9767        // after confirming that all the receivers processed the ordered
   9768        // broadcast when packages get disabled, force a gc to clean things up.
   9769        // and unload all the containers.
   9770        if (pkgList.size() > 0) {
   9771            sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
   9772                public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
   9773                        boolean ordered, boolean sticky) throws RemoteException {
   9774                    Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
   9775                            reportStatus ? 1 : 0, 1, keys);
   9776                    mHandler.sendMessage(msg);
   9777                }
   9778            });
   9779        } else {
   9780            Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
   9781                    reportStatus ? 1 : 0, -1, keys);
   9782            mHandler.sendMessage(msg);
   9783        }
   9784    }
   9785 
   9786    public void movePackage(final String packageName,
   9787            final IPackageMoveObserver observer, final int flags) {
   9788        mContext.enforceCallingOrSelfPermission(
   9789                android.Manifest.permission.MOVE_PACKAGE, null);
   9790        int returnCode = PackageManager.MOVE_SUCCEEDED;
   9791        int currFlags = 0;
   9792        int newFlags = 0;
   9793        synchronized (mPackages) {
   9794            PackageParser.Package pkg = mPackages.get(packageName);
   9795            if (pkg == null) {
   9796                returnCode =  PackageManager.MOVE_FAILED_DOESNT_EXIST;
   9797            } else {
   9798                // Disable moving fwd locked apps and system packages
   9799                if (pkg.applicationInfo != null &&
   9800                        (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
   9801                    Slog.w(TAG, "Cannot move system application");
   9802                    returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
   9803                } else if (pkg.applicationInfo != null &&
   9804                        (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
   9805                    Slog.w(TAG, "Cannot move forward locked app.");
   9806                    returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
   9807                } else {
   9808                    // Find install location first
   9809                    if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
   9810                            (flags & PackageManager.MOVE_INTERNAL) != 0) {
   9811                        Slog.w(TAG, "Ambigous flags specified for move location.");
   9812                        returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
   9813                    } else {
   9814                        newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
   9815                                PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
   9816                        currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
   9817                                PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
   9818                        if (newFlags == currFlags) {
   9819                            Slog.w(TAG, "No move required. Trying to move to same location");
   9820                            returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
   9821                        }
   9822                    }
   9823                }
   9824            }
   9825            if (returnCode != PackageManager.MOVE_SUCCEEDED) {
   9826                processPendingMove(new MoveParams(null, observer, 0, packageName), returnCode);
   9827            } else {
   9828                Message msg = mHandler.obtainMessage(INIT_COPY);
   9829                InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
   9830                        pkg.applicationInfo.publicSourceDir);
   9831                MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
   9832                        packageName);
   9833                msg.obj = mp;
   9834                mHandler.sendMessage(msg);
   9835            }
   9836        }
   9837    }
   9838 
   9839    private void processPendingMove(final MoveParams mp, final int currentStatus) {
   9840        // Queue up an async operation since the package deletion may take a little while.
   9841        mHandler.post(new Runnable() {
   9842            public void run() {
   9843                mHandler.removeCallbacks(this);
   9844                int returnCode = currentStatus;
   9845                if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
   9846                    int uidArr[] = null;
   9847                    ArrayList<String> pkgList = null;
   9848                    synchronized (mPackages) {
   9849                        PackageParser.Package pkg = mPackages.get(mp.packageName);
   9850                        if (pkg == null ) {
   9851                            Slog.w(TAG, " Package " + mp.packageName +
   9852                            " doesn't exist. Aborting move");
   9853                            returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
   9854                        } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
   9855                            Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
   9856                                    mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
   9857                            " Aborting move and returning error");
   9858                            returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
   9859                        } else {
   9860                            uidArr = new int[] { pkg.applicationInfo.uid };
   9861                            pkgList = new ArrayList<String>();
   9862                            pkgList.add(mp.packageName);
   9863                        }
   9864                    }
   9865                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
   9866                        // Send resources unavailable broadcast
   9867                        sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
   9868                        // Update package code and resource paths
   9869                        synchronized (mInstallLock) {
   9870                            synchronized (mPackages) {
   9871                                PackageParser.Package pkg = mPackages.get(mp.packageName);
   9872                                // Recheck for package again.
   9873                                if (pkg == null ) {
   9874                                    Slog.w(TAG, " Package " + mp.packageName +
   9875                                    " doesn't exist. Aborting move");
   9876                                    returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
   9877                                } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
   9878                                    Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
   9879                                            mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
   9880                                    " Aborting move and returning error");
   9881                                    returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
   9882                                } else {
   9883                                    String oldCodePath = pkg.mPath;
   9884                                    String newCodePath = mp.targetArgs.getCodePath();
   9885                                    String newResPath = mp.targetArgs.getResourcePath();
   9886                                    pkg.mPath = newCodePath;
   9887                                    // Move dex files around
   9888                                    if (moveDexFilesLI(pkg)
   9889                                            != PackageManager.INSTALL_SUCCEEDED) {
   9890                                        // Moving of dex files failed. Set
   9891                                        // error code and abort move.
   9892                                        pkg.mPath = pkg.mScanPath;
   9893                                        returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
   9894                                    } else {
   9895                                        pkg.mScanPath = newCodePath;
   9896                                        pkg.applicationInfo.sourceDir = newCodePath;
   9897                                        pkg.applicationInfo.publicSourceDir = newResPath;
   9898                                        PackageSetting ps = (PackageSetting) pkg.mExtras;
   9899                                        ps.codePath = new File(pkg.applicationInfo.sourceDir);
   9900                                        ps.codePathString = ps.codePath.getPath();
   9901                                        ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
   9902                                        ps.resourcePathString = ps.resourcePath.getPath();
   9903                                        // Set the application info flag correctly.
   9904                                        if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
   9905                                            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
   9906                                        } else {
   9907                                            pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
   9908                                        }
   9909                                        ps.setFlags(pkg.applicationInfo.flags);
   9910                                        mAppDirs.remove(oldCodePath);
   9911                                        mAppDirs.put(newCodePath, pkg);
   9912                                        // Persist settings
   9913                                        mSettings.writeLP();
   9914                                    }
   9915                                }
   9916                            }
   9917                        }
   9918                        // Send resources available broadcast
   9919                        sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
   9920                    }
   9921                }
   9922                if (returnCode != PackageManager.MOVE_SUCCEEDED){
   9923                    // Clean up failed installation
   9924                    if (mp.targetArgs != null) {
   9925                        mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
   9926                    }
   9927                } else {
   9928                    // Force a gc to clear things up.
   9929                    Runtime.getRuntime().gc();
   9930                    // Delete older code
   9931                    synchronized (mInstallLock) {
   9932                        mp.srcArgs.doPostDeleteLI(true);
   9933                    }
   9934                }
   9935                IPackageMoveObserver observer = mp.observer;
   9936                if (observer != null) {
   9937                    try {
   9938                        observer.packageMoved(mp.packageName, returnCode);
   9939                    } catch (RemoteException e) {
   9940                        Log.i(TAG, "Observer no longer exists.");
   9941                    }
   9942                }
   9943            }
   9944        });
   9945    }
   9946 
   9947    public boolean setInstallLocation(int loc) {
   9948        mContext.enforceCallingOrSelfPermission(
   9949                android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
   9950        if (getInstallLocation() == loc) {
   9951            return true;
   9952        }
   9953        if (loc == PackageHelper.APP_INSTALL_AUTO ||
   9954                loc == PackageHelper.APP_INSTALL_INTERNAL ||
   9955                loc == PackageHelper.APP_INSTALL_EXTERNAL) {
   9956            android.provider.Settings.System.putInt(mContext.getContentResolver(),
   9957                    android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
   9958            return true;
   9959        }
   9960        return false;
   9961    }
   9962 
   9963    public int getInstallLocation() {
   9964        return android.provider.Settings.System.getInt(mContext.getContentResolver(),
   9965                android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO);
   9966    }
   9967 }
   9968