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