diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java index b0d2158b45364..fc5443e54d999 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -56,7 +56,7 @@ import android.util.Slog; * settings parameter with a default value of 2MB), the free memory is * logged to the event log. */ -class DeviceStorageMonitorService extends Binder { +public class DeviceStorageMonitorService extends Binder { private static final String TAG = "DeviceStorageMonitorService"; private static final boolean DEBUG = false; private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; @@ -99,7 +99,7 @@ class DeviceStorageMonitorService extends Binder { /** * This string is used for ServiceManager access to this class. */ - static final String SERVICE = "devicestoragemonitor"; + public static final String SERVICE = "devicestoragemonitor"; /** * Handler that checks the amount of disk space on the device and sends a diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 91ada6bf52b1d..4e80147d0e645 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -18,6 +18,7 @@ package com.android.server; import com.android.internal.app.IMediaContainerService; import com.android.server.am.ActivityManagerService; +import com.android.server.pm.PackageManagerService; import android.Manifest; import android.content.BroadcastReceiver; @@ -86,6 +87,9 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC private static final String VOLD_TAG = "VoldConnector"; + /** Maximum number of ASEC containers allowed to be mounted. */ + private static final int MAX_CONTAINERS = 250; + /* * Internal vold volume state constants */ @@ -483,7 +487,6 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC } } }; - private final class MountServiceBinderListener implements IBinder.DeathRecipient { final IMountServiceListener mListener; @@ -1087,8 +1090,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC * amount of containers we'd ever expect to have. This keeps an * "asec list" from blocking a thread repeatedly. */ - mConnector = new NativeDaemonConnector(this, "vold", - PackageManagerService.MAX_CONTAINERS * 2, VOLD_TAG); + mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG); mReady = false; Thread thread = new Thread(mConnector, VOLD_TAG); thread.start(); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index d1609630646d4..4e1bbacb1d5f5 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -17,6 +17,7 @@ package com.android.server; import com.android.server.am.ActivityManagerService; +import com.android.server.pm.PackageManagerService; import com.android.server.usb.UsbService; import com.android.server.wm.WindowManagerService; import com.android.internal.app.ShutdownThread; diff --git a/services/java/com/android/server/pm/BasePermission.java b/services/java/com/android/server/pm/BasePermission.java new file mode 100644 index 0000000000000..4f27408a6ffff --- /dev/null +++ b/services/java/com/android/server/pm/BasePermission.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.PackageParser; +import android.content.pm.PermissionInfo; + +final class BasePermission { + final static int TYPE_NORMAL = 0; + + final static int TYPE_BUILTIN = 1; + + final static int TYPE_DYNAMIC = 2; + + final String name; + + String sourcePackage; + + PackageSettingBase packageSetting; + + final int type; + + int protectionLevel; + + PackageParser.Permission perm; + + PermissionInfo pendingInfo; + + int uid; + + int[] gids; + + BasePermission(String _name, String _sourcePackage, int _type) { + name = _name; + sourcePackage = _sourcePackage; + type = _type; + // Default to most conservative protection level. + protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; + } + + public String toString() { + return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + name + + "}"; + } +} diff --git a/services/java/com/android/server/pm/GrantedPermissions.java b/services/java/com/android/server/pm/GrantedPermissions.java new file mode 100644 index 0000000000000..c7629b98635e5 --- /dev/null +++ b/services/java/com/android/server/pm/GrantedPermissions.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.ApplicationInfo; + +import java.util.HashSet; + +class GrantedPermissions { + int pkgFlags; + + HashSet grantedPermissions = new HashSet(); + + int[] gids; + + GrantedPermissions(int pkgFlags) { + setFlags(pkgFlags); + } + + @SuppressWarnings("unchecked") + GrantedPermissions(GrantedPermissions base) { + pkgFlags = base.pkgFlags; + grantedPermissions = (HashSet) base.grantedPermissions.clone(); + + if (base.gids != null) { + gids = base.gids.clone(); + } + } + + void setFlags(int pkgFlags) { + this.pkgFlags = pkgFlags + & (ApplicationInfo.FLAG_SYSTEM + | ApplicationInfo.FLAG_FORWARD_LOCK + | ApplicationInfo.FLAG_EXTERNAL_STORAGE); + } +} diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/pm/Installer.java similarity index 66% rename from services/java/com/android/server/Installer.java rename to services/java/com/android/server/pm/Installer.java index 08d1b82f25206..8d40000b15714 100644 --- a/services/java/com/android/server/Installer.java +++ b/services/java/com/android/server/pm/Installer.java @@ -14,28 +14,31 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pm; import android.content.pm.PackageStats; -import android.net.LocalSocketAddress; import android.net.LocalSocket; -import android.util.Config; +import android.net.LocalSocketAddress; import android.util.Slog; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.Socket; - class Installer { private static final String TAG = "Installer"; - InputStream mIn; - OutputStream mOut; - LocalSocket mSocket; - byte buf[] = new byte[1024]; - int buflen = 0; + private static final boolean LOCAL_DEBUG = true; + + InputStream mIn; + + OutputStream mOut; + + LocalSocket mSocket; + + byte buf[] = new byte[1024]; + + int buflen = 0; private boolean connect() { if (mSocket != null) { @@ -45,8 +48,8 @@ class Installer { try { mSocket = new LocalSocket(); - LocalSocketAddress address = new LocalSocketAddress( - "installd", LocalSocketAddress.Namespace.RESERVED); + LocalSocketAddress address = new LocalSocketAddress("installd", + LocalSocketAddress.Namespace.RESERVED); mSocket.connect(address); @@ -59,112 +62,131 @@ class Installer { return true; } - private void disconnect() { - Slog.i(TAG,"disconnecting..."); - try { - if (mSocket != null) mSocket.close(); - } catch (IOException ex) { } - try { - if (mIn != null) mIn.close(); - } catch (IOException ex) { } - try { - if (mOut != null) mOut.close(); - } catch (IOException ex) { } - mSocket = null; - mIn = null; - mOut = null; - } + private void disconnect() { + Slog.i(TAG, "disconnecting..."); + try { + if (mSocket != null) + mSocket.close(); + } catch (IOException ex) { + } + try { + if (mIn != null) + mIn.close(); + } catch (IOException ex) { + } + try { + if (mOut != null) + mOut.close(); + } catch (IOException ex) { + } + mSocket = null; + mIn = null; + mOut = null; + } - private boolean readBytes(byte buffer[], int len) { - int off = 0, count; - if (len < 0) return false; - while (off != len) { - try { - count = mIn.read(buffer, off, len - off); - if (count <= 0) { + private boolean readBytes(byte buffer[], int len) { + int off = 0, count; + if (len < 0) + return false; + while (off != len) { + try { + count = mIn.read(buffer, off, len - off); + if (count <= 0) { Slog.e(TAG, "read error " + count); break; } - off += count; - } catch (IOException ex) { - Slog.e(TAG,"read exception"); - break; - } - } -// Slog.i(TAG, "read "+len+" bytes"); - if (off == len) return true; - disconnect(); - return false; - } + off += count; + } catch (IOException ex) { + Slog.e(TAG, "read exception"); + break; + } + } + if (LOCAL_DEBUG) { + Slog.i(TAG, "read " + len + " bytes"); + } + if (off == len) + return true; + disconnect(); + return false; + } - private boolean readReply() { - int len; - buflen = 0; - if (!readBytes(buf, 2)) return false; - len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8); - if ((len < 1) || (len > 1024)) { - Slog.e(TAG,"invalid reply length ("+len+")"); - disconnect(); - return false; - } - if (!readBytes(buf, len)) return false; - buflen = len; - return true; - } + private boolean readReply() { + int len; + buflen = 0; + if (!readBytes(buf, 2)) + return false; + len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8); + if ((len < 1) || (len > 1024)) { + Slog.e(TAG, "invalid reply length (" + len + ")"); + disconnect(); + return false; + } + if (!readBytes(buf, len)) + return false; + buflen = len; + return true; + } - private boolean writeCommand(String _cmd) { - byte[] cmd = _cmd.getBytes(); - int len = cmd.length; - if ((len < 1) || (len > 1024)) return false; - buf[0] = (byte) (len & 0xff); - buf[1] = (byte) ((len >> 8) & 0xff); - try { - mOut.write(buf, 0, 2); - mOut.write(cmd, 0, len); - } catch (IOException ex) { - Slog.e(TAG,"write error"); - disconnect(); - return false; - } - return true; - } - - private synchronized String transaction(String cmd) { - if (!connect()) { + private boolean writeCommand(String _cmd) { + byte[] cmd = _cmd.getBytes(); + int len = cmd.length; + if ((len < 1) || (len > 1024)) + return false; + buf[0] = (byte) (len & 0xff); + buf[1] = (byte) ((len >> 8) & 0xff); + try { + mOut.write(buf, 0, 2); + mOut.write(cmd, 0, len); + } catch (IOException ex) { + Slog.e(TAG, "write error"); + disconnect(); + return false; + } + return true; + } + + private synchronized String transaction(String cmd) { + if (!connect()) { Slog.e(TAG, "connection failed"); return "-1"; } if (!writeCommand(cmd)) { - /* If installd died and restarted in the background - * (unlikely but possible) we'll fail on the next - * write (this one). Try to reconnect and write - * the command one more time before giving up. - */ + /* + * If installd died and restarted in the background (unlikely but + * possible) we'll fail on the next write (this one). Try to + * reconnect and write the command one more time before giving up. + */ Slog.e(TAG, "write command failed? reconnect!"); if (!connect() || !writeCommand(cmd)) { return "-1"; } } -// Slog.i(TAG,"send: '"+cmd+"'"); - if (readReply()) { + if (LOCAL_DEBUG) { + Slog.i(TAG, "send: '" + cmd + "'"); + } + if (readReply()) { String s = new String(buf, 0, buflen); -// Slog.i(TAG,"recv: '"+s+"'"); - return s; - } else { -// Slog.i(TAG,"fail"); - return "-1"; - } - } + if (LOCAL_DEBUG) { + Slog.i(TAG, "recv: '" + s + "'"); + } + return s; + } else { + if (LOCAL_DEBUG) { + Slog.i(TAG, "fail"); + } + return "-1"; + } + } - private int execute(String cmd) { - String res = transaction(cmd); - try { - return Integer.parseInt(res); - } catch (NumberFormatException ex) { - return -1; - } - } + private int execute(String cmd) { + String res = transaction(cmd); + try { + return Integer.parseInt(res); + } catch (NumberFormatException ex) { + return -1; + } + } public int install(String name, int uid, int gid) { StringBuilder builder = new StringBuilder("install"); @@ -225,14 +247,14 @@ class Installer { builder.append(name); return execute(builder.toString()); } - + public int clearUserData(String name) { StringBuilder builder = new StringBuilder("rmuserdata"); builder.append(' '); builder.append(name); return execute(builder.toString()); } - + public boolean ping() { if (execute("ping") < 0) { return false; @@ -240,7 +262,7 @@ class Installer { return true; } } - + public int freeCache(long freeStorageSize) { StringBuilder builder = new StringBuilder("freecache"); builder.append(' '); @@ -250,8 +272,8 @@ class Installer { /* * @param packagePathSuffix The name of the path relative to install - * directory. Say if the path name is /data/app/com.test-1.apk, - * the package suffix path will be com.test-1 + * directory. Say if the path name is /data/app/com.test-1.apk, the package + * suffix path will be com.test-1 */ public int setForwardLockPerm(String packagePathSuffix, int gid) { StringBuilder builder = new StringBuilder("protect"); @@ -261,7 +283,7 @@ class Installer { builder.append(gid); return execute(builder.toString()); } - + public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath, PackageStats pStats) { StringBuilder builder = new StringBuilder("getsize"); @@ -275,7 +297,7 @@ class Installer { String s = transaction(builder.toString()); String res[] = s.split(" "); - if((res == null) || (res.length != 4)) { + if ((res == null) || (res.length != 4)) { return -1; } try { @@ -286,7 +308,7 @@ class Installer { } catch (NumberFormatException e) { return -1; } - } + } public int moveFiles() { return execute("movefiles"); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java similarity index 65% rename from services/java/com/android/server/PackageManagerService.java rename to services/java/com/android/server/pm/PackageManagerService.java index 3d8dccb0f2a23..669e060a1540b 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pm; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; @@ -24,13 +24,13 @@ import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; -import com.android.internal.util.FastXmlSerializer; -import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; +import com.android.server.DeviceStorageMonitorService; +import com.android.server.EventLogTags; +import com.android.server.IntentResolver; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import android.app.ActivityManagerNative; import android.app.IActivityManager; @@ -46,7 +46,6 @@ import android.content.ServiceConnection; import android.content.IntentSender.SendIntentException; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; -import android.content.pm.ComponentInfo; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; @@ -96,7 +95,6 @@ import android.util.Xml; import android.view.Display; import android.view.WindowManager; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -135,15 +133,15 @@ import java.util.zip.ZipOutputStream; mmm frameworks/base/tests/AndroidTests adb install -r -f out/target/product/passion/data/app/AndroidTests.apk adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner - * + * + * {@hide} */ -class PackageManagerService extends IPackageManager.Stub { - private static final String TAG = "PackageManager"; - private static final boolean DEBUG_SETTINGS = false; +public class PackageManagerService extends IPackageManager.Stub { + static final String TAG = "PackageManager"; + static final boolean DEBUG_SETTINGS = false; private static final boolean DEBUG_PREFERRED = false; - private static final boolean DEBUG_UPGRADE = false; + static final boolean DEBUG_UPGRADE = false; private static final boolean DEBUG_INSTALL = false; - private static final boolean DEBUG_STOPPED = false; private static final boolean DEBUG_REMOVE = false; private static final boolean DEBUG_SHOW_INFO = false; private static final boolean DEBUG_PACKAGE_INFO = false; @@ -151,13 +149,13 @@ class PackageManagerService extends IPackageManager.Stub { private static final boolean DEBUG_PACKAGE_SCANNING = false; private static final boolean DEBUG_APP_DIR_OBSERVER = false; - private static final boolean MULTIPLE_APPLICATION_UIDS = true; + static final boolean MULTIPLE_APPLICATION_UIDS = true; private static final int RADIO_UID = Process.PHONE_UID; private static final int LOG_UID = Process.LOG_UID; private static final int NFC_UID = Process.NFC_UID; - private static final int FIRST_APPLICATION_UID = + static final int FIRST_APPLICATION_UID = Process.FIRST_APPLICATION_UID; - private static final int MAX_APPLICATION_UIDS = 1000; + static final int MAX_APPLICATION_UIDS = 1000; private static final boolean GET_CERTIFICATES = true; @@ -171,19 +169,6 @@ class PackageManagerService extends IPackageManager.Stub { // package apks to install directory. private static final String INSTALL_PACKAGE_SUFFIX = "-"; - /** - * Indicates the state of installation. Used by PackageManager to - * figure out incomplete installations. Say a package is being installed - * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till - * the package installation is successful or unsuccesful lin which case - * the PackageManager will no longer maintain state information associated - * with the package. If some exception(like device freeze or battery being - * pulled out) occurs during installation of a package, the PackageManager - * needs this information to clean up the previously failed installation. - */ - private static final int PKG_INSTALL_INCOMPLETE = 0; - private static final int PKG_INSTALL_COMPLETE = 1; - static final int SCAN_MONITOR = 1<<0; static final int SCAN_NO_DEX = 1<<1; static final int SCAN_FORCE_DEX = 1<<2; @@ -672,7 +657,7 @@ class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { removeMessages(WRITE_SETTINGS); removeMessages(WRITE_STOPPED_PACKAGES); - mSettings.writeLP(); + mSettings.writeLPr(); } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } break; @@ -680,7 +665,7 @@ class PackageManagerService extends IPackageManager.Stub { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); synchronized (mPackages) { removeMessages(WRITE_STOPPED_PACKAGES); - mSettings.writeStoppedLP(); + mSettings.writeStoppedLPr(); } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } break; @@ -752,17 +737,17 @@ class PackageManagerService extends IPackageManager.Stub { mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type")); mMetrics = new DisplayMetrics(); mSettings = new Settings(); - mSettings.addSharedUserLP("android.uid.system", + mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM); - mSettings.addSharedUserLP("android.uid.phone", + mSettings.addSharedUserLPw("android.uid.phone", MULTIPLE_APPLICATION_UIDS ? RADIO_UID : FIRST_APPLICATION_UID, ApplicationInfo.FLAG_SYSTEM); - mSettings.addSharedUserLP("android.uid.log", + mSettings.addSharedUserLPw("android.uid.log", MULTIPLE_APPLICATION_UIDS ? LOG_UID : FIRST_APPLICATION_UID, ApplicationInfo.FLAG_SYSTEM); - mSettings.addSharedUserLP("android.uid.nfc", + mSettings.addSharedUserLPw("android.uid.nfc", MULTIPLE_APPLICATION_UIDS ? NFC_UID : FIRST_APPLICATION_UID, ApplicationInfo.FLAG_SYSTEM); @@ -800,6 +785,7 @@ class PackageManagerService extends IPackageManager.Stub { d.getMetrics(mMetrics); synchronized (mInstallLock) { + // writer synchronized (mPackages) { mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); @@ -820,7 +806,7 @@ class PackageManagerService extends IPackageManager.Stub { readPermissions(); - mRestoredSettings = mSettings.readLP(); + mRestoredSettings = mSettings.readLPw(); long startTime = SystemClock.uptimeMillis(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, @@ -995,7 +981,7 @@ class PackageManagerService extends IPackageManager.Stub { mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists } //look for any incomplete package installations - ArrayList deletePkgsList = mSettings.getListOfIncompleteInstallPackages(); + ArrayList deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); //clean up list for(int i = 0; i < deletePkgsList.size(); i++) { //clean up here @@ -1036,9 +1022,10 @@ class PackageManagerService extends IPackageManager.Stub { + "; regranting permissions for internal storage"); mSettings.mInternalSdkPlatform = mSdkVersion; - updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions); + updatePermissionsLPw(null, null, true, regrantPermissions, regrantPermissions); - mSettings.writeLP(); + // can downgrade to reader + mSettings.writeLPr(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); @@ -1088,7 +1075,7 @@ class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath); } } - mSettings.removePackageLP(ps.name); + mSettings.removePackageLPw(ps.name); } void readPermissions() { @@ -1355,6 +1342,7 @@ class PackageManagerService extends IPackageManager.Stub { } public PackageInfo getPackageInfo(String packageName, int flags) { + // reader synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (DEBUG_PACKAGE_INFO) @@ -1363,7 +1351,7 @@ class PackageManagerService extends IPackageManager.Stub { return generatePackageInfo(p, flags); } if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { - return generatePackageInfoFromSettingsLP(packageName, flags); + return generatePackageInfoFromSettingsLPw(packageName, flags); } } return null; @@ -1371,6 +1359,7 @@ class PackageManagerService extends IPackageManager.Stub { public String[] currentToCanonicalPackageNames(String[] names) { String[] out = new String[names.length]; + // reader synchronized (mPackages) { for (int i=names.length-1; i>=0; i--) { PackageSetting ps = mSettings.mPackages.get(names[i]); @@ -1382,6 +1371,7 @@ class PackageManagerService extends IPackageManager.Stub { public String[] canonicalToCurrentPackageNames(String[] names) { String[] out = new String[names.length]; + // reader synchronized (mPackages) { for (int i=names.length-1; i>=0; i--) { String cur = mSettings.mRenamedPackages.get(names[i]); @@ -1392,6 +1382,7 @@ class PackageManagerService extends IPackageManager.Stub { } public int getPackageUid(String packageName) { + // reader synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if(p != null) { @@ -1407,6 +1398,7 @@ class PackageManagerService extends IPackageManager.Stub { } public int[] getPackageGids(String packageName) { + // reader synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (DEBUG_PACKAGE_INFO) @@ -1435,6 +1427,7 @@ class PackageManagerService extends IPackageManager.Stub { } public PermissionInfo getPermissionInfo(String name, int flags) { + // reader synchronized (mPackages) { final BasePermission p = mSettings.mPermissions.get(name); if (p != null) { @@ -1445,6 +1438,7 @@ class PackageManagerService extends IPackageManager.Stub { } public List queryPermissionsByGroup(String group, int flags) { + // reader synchronized (mPackages) { ArrayList out = new ArrayList(10); for (BasePermission p : mSettings.mPermissions.values()) { @@ -1467,6 +1461,7 @@ class PackageManagerService extends IPackageManager.Stub { } public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) { + // reader synchronized (mPackages) { return PackageParser.generatePermissionGroupInfo( mPermissionGroups.get(name), flags); @@ -1474,6 +1469,7 @@ class PackageManagerService extends IPackageManager.Stub { } public List getAllPermissionGroups(int flags) { + // reader synchronized (mPackages) { final int N = mPermissionGroups.size(); ArrayList out @@ -1485,12 +1481,12 @@ class PackageManagerService extends IPackageManager.Stub { } } - private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) { + private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags) { PackageSetting ps = mSettings.mPackages.get(packageName); - if(ps != null) { - if(ps.pkg == null) { - PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags); - if(pInfo != null) { + if (ps != null) { + if (ps.pkg == null) { + PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags); + if (pInfo != null) { return pInfo.applicationInfo; } return null; @@ -1500,10 +1496,10 @@ class PackageManagerService extends IPackageManager.Stub { return null; } - private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) { + private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags) { PackageSetting ps = mSettings.mPackages.get(packageName); - if(ps != null) { - if(ps.pkg == null) { + if (ps != null) { + if (ps.pkg == null) { ps.pkg = new PackageParser.Package(packageName); ps.pkg.applicationInfo.packageName = packageName; ps.pkg.applicationInfo.flags = ps.pkgFlags; @@ -1520,6 +1516,7 @@ class PackageManagerService extends IPackageManager.Stub { } public ApplicationInfo getApplicationInfo(String packageName, int flags) { + // writer synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (DEBUG_PACKAGE_INFO) Log.v( @@ -1533,7 +1530,7 @@ class PackageManagerService extends IPackageManager.Stub { return mAndroidApplication; } if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { - return generateApplicationInfoFromSettingsLP(packageName, flags); + return generateApplicationInfoFromSettingsLPw(packageName, flags); } } return null; @@ -1598,7 +1595,7 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Activity a = mActivities.mActivities.get(component); if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a); - if (a != null && mSettings.isEnabledLP(a.info, flags)) { + if (a != null && mSettings.isEnabledLPr(a.info, flags)) { return PackageParser.generateActivityInfo(a, flags); } if (mResolveComponentName.equals(component)) { @@ -1613,7 +1610,7 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Activity a = mReceivers.mActivities.get(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getReceiverInfo " + component + ": " + a); - if (a != null && mSettings.isEnabledLP(a.info, flags)) { + if (a != null && mSettings.isEnabledLPr(a.info, flags)) { return PackageParser.generateActivityInfo(a, flags); } } @@ -1625,7 +1622,7 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Service s = mServices.mServices.get(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getServiceInfo " + component + ": " + s); - if (s != null && mSettings.isEnabledLP(s.info, flags)) { + if (s != null && mSettings.isEnabledLPr(s.info, flags)) { return PackageParser.generateServiceInfo(s, flags); } } @@ -1637,7 +1634,7 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Provider p = mProvidersByComponent.get(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getProviderInfo " + component + ": " + p); - if (p != null && mSettings.isEnabledLP(p.info, flags)) { + if (p != null && mSettings.isEnabledLPr(p.info, flags)) { return PackageParser.generateProviderInfo(p, flags); } } @@ -1701,7 +1698,7 @@ class PackageManagerService extends IPackageManager.Stub { public int checkUidPermission(String permName, int uid) { synchronized (mPackages) { - Object obj = mSettings.getUserIdLP(uid); + Object obj = mSettings.getUserIdLPr(uid); if (obj != null) { GrantedPermissions gp = (GrantedPermissions)obj; if (gp.grantedPermissions.contains(permName)) { @@ -1806,7 +1803,7 @@ class PackageManagerService extends IPackageManager.Stub { } if (changed) { if (!async) { - mSettings.writeLP(); + mSettings.writeLPr(); } else { scheduleWriteSettingsLocked(); } @@ -1837,7 +1834,7 @@ class PackageManagerService extends IPackageManager.Stub { + name); } mSettings.mPermissions.remove(name); - mSettings.writeLP(); + mSettings.writeLPr(); } } } @@ -1850,21 +1847,22 @@ class PackageManagerService extends IPackageManager.Stub { public int checkSignatures(String pkg1, String pkg2) { synchronized (mPackages) { - PackageParser.Package p1 = mPackages.get(pkg1); - PackageParser.Package p2 = mPackages.get(pkg2); + final PackageParser.Package p1 = mPackages.get(pkg1); + final PackageParser.Package p2 = mPackages.get(pkg2); if (p1 == null || p1.mExtras == null || p2 == null || p2.mExtras == null) { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } - return checkSignaturesLP(p1.mSignatures, p2.mSignatures); + return compareSignatures(p1.mSignatures, p2.mSignatures); } } public int checkUidSignatures(int uid1, int uid2) { + // reader synchronized (mPackages) { Signature[] s1; Signature[] s2; - Object obj = mSettings.getUserIdLP(uid1); + Object obj = mSettings.getUserIdLPr(uid1); if (obj != null) { if (obj instanceof SharedUserSetting) { s1 = ((SharedUserSetting)obj).signatures.mSignatures; @@ -1876,7 +1874,7 @@ class PackageManagerService extends IPackageManager.Stub { } else { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } - obj = mSettings.getUserIdLP(uid2); + obj = mSettings.getUserIdLPr(uid2); if (obj != null) { if (obj instanceof SharedUserSetting) { s2 = ((SharedUserSetting)obj).signatures.mSignatures; @@ -1888,11 +1886,11 @@ class PackageManagerService extends IPackageManager.Stub { } else { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } - return checkSignaturesLP(s1, s2); + return compareSignatures(s1, s2); } } - int checkSignaturesLP(Signature[] s1, Signature[] s2) { + static int compareSignatures(Signature[] s1, Signature[] s2) { if (s1 == null) { return s2 == null ? PackageManager.SIGNATURE_NEITHER_SIGNED @@ -1917,20 +1915,21 @@ class PackageManagerService extends IPackageManager.Stub { } public String[] getPackagesForUid(int uid) { + // reader synchronized (mPackages) { - Object obj = mSettings.getUserIdLP(uid); + Object obj = mSettings.getUserIdLPr(uid); if (obj instanceof SharedUserSetting) { - SharedUserSetting sus = (SharedUserSetting)obj; + final SharedUserSetting sus = (SharedUserSetting) obj; final int N = sus.packages.size(); - String[] res = new String[N]; - Iterator it = sus.packages.iterator(); - int i=0; + final String[] res = new String[N]; + final Iterator it = sus.packages.iterator(); + int i = 0; while (it.hasNext()) { res[i++] = it.next().name; } return res; } else if (obj instanceof PackageSetting) { - PackageSetting ps = (PackageSetting)obj; + final PackageSetting ps = (PackageSetting) obj; return new String[] { ps.name }; } } @@ -1938,13 +1937,14 @@ class PackageManagerService extends IPackageManager.Stub { } public String getNameForUid(int uid) { + // reader synchronized (mPackages) { - Object obj = mSettings.getUserIdLP(uid); + Object obj = mSettings.getUserIdLPr(uid); if (obj instanceof SharedUserSetting) { - SharedUserSetting sus = (SharedUserSetting)obj; + final SharedUserSetting sus = (SharedUserSetting) obj; return sus.name + ":" + sus.userId; } else if (obj instanceof PackageSetting) { - PackageSetting ps = (PackageSetting)obj; + final PackageSetting ps = (PackageSetting) obj; return ps.name; } } @@ -1955,8 +1955,9 @@ class PackageManagerService extends IPackageManager.Stub { if(sharedUserName == null) { return -1; } + // reader synchronized (mPackages) { - SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false); + final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false); if(suid == null) { return -1; } @@ -2007,6 +2008,7 @@ class PackageManagerService extends IPackageManager.Stub { ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags, List query, int priority) { + // writer synchronized (mPackages) { if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); List prefs = @@ -2017,24 +2019,35 @@ class PackageManagerService extends IPackageManager.Stub { // We will only allow preferred activities that came // from the same match quality. int match = 0; - final int N = query.size(); - if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match..."); - for (int j=0; j match) match = ri.match; + + if (DEBUG_PREFERRED) { + Log.v(TAG, "Figuring out best match..."); } - if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x" - + Integer.toHexString(match)); + + final int N = query.size(); + for (int j=0; j match) { + match = ri.match; + } + } + + if (DEBUG_PREFERRED) { + Log.v(TAG, "Best match: 0x" + Integer.toHexString(match)); + } + match &= IntentFilter.MATCH_CATEGORY_MASK; final int M = prefs.size(); for (int i=0; i queryIntentActivities(Intent intent, String resolvedType, int flags) { - ComponentName comp = intent.getComponent(); + final ComponentName comp = intent.getComponent(); if (comp != null) { - List list = new ArrayList(1); - ActivityInfo ai = getActivityInfo(comp, flags); + final List list = new ArrayList(1); + final ActivityInfo ai = getActivityInfo(comp, flags); if (ai != null) { - ResolveInfo ri = new ResolveInfo(); + final ResolveInfo ri = new ResolveInfo(); ri.activityInfo = ai; list.add(ri); } return list; } + // reader synchronized (mPackages) { - String pkgName = intent.getPackage(); + final String pkgName = intent.getPackage(); if (pkgName == null) { - return (List)mActivities.queryIntent(intent, - resolvedType, flags); + return mActivities.queryIntent(intent, resolvedType, flags); } - PackageParser.Package pkg = mPackages.get(pkgName); + final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { - return (List) mActivities.queryIntentForPackage(intent, - resolvedType, flags, pkg.activities); + return mActivities.queryIntentForPackage(intent, resolvedType, flags, + pkg.activities); } return new ArrayList(); } @@ -2109,9 +2122,12 @@ class PackageManagerService extends IPackageManager.Stub { String resolvedType, int flags) { final String resultsAction = intent.getAction(); - List results = queryIntentActivities( - intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER); - if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Query " + intent + ": " + results); + List results = queryIntentActivities(intent, resolvedType, flags + | PackageManager.GET_RESOLVED_FILTER); + + if (DEBUG_INTENT_MATCHING) { + Log.v(TAG, "Query " + intent + ": " + results); + } int specificsPos = 0; int N; @@ -2131,16 +2147,21 @@ class PackageManagerService extends IPackageManager.Stub { continue; } - if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + sintent); + if (DEBUG_INTENT_MATCHING) { + Log.v(TAG, "Specific #" + i + ": " + sintent); + } + String action = sintent.getAction(); if (resultsAction != null && resultsAction.equals(action)) { // If this action was explicitly requested, then don't // remove things that have it. action = null; } - ComponentName comp = sintent.getComponent(); + ResolveInfo ri = null; ActivityInfo ai = null; + + ComponentName comp = sintent.getComponent(); if (comp == null) { ri = resolveIntent( sintent, @@ -2265,8 +2286,7 @@ class PackageManagerService extends IPackageManager.Stub { return results; } - public List queryIntentReceivers(Intent intent, - String resolvedType, int flags) { + public List queryIntentReceivers(Intent intent, String resolvedType, int flags) { ComponentName comp = intent.getComponent(); if (comp != null) { List list = new ArrayList(1); @@ -2279,25 +2299,22 @@ class PackageManagerService extends IPackageManager.Stub { return list; } + // reader synchronized (mPackages) { String pkgName = intent.getPackage(); if (pkgName == null) { - return (List)mReceivers.queryIntent(intent, - resolvedType, flags); + return mReceivers.queryIntent(intent, resolvedType, flags); } - PackageParser.Package pkg = mPackages.get(pkgName); + final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { - return (List) mReceivers.queryIntentForPackage(intent, - resolvedType, flags, pkg.receivers); + return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers); } return null; } } - public ResolveInfo resolveService(Intent intent, String resolvedType, - int flags) { - List query = queryIntentServices(intent, resolvedType, - flags); + public ResolveInfo resolveService(Intent intent, String resolvedType, int flags) { + List query = queryIntentServices(intent, resolvedType, flags); if (query != null) { if (query.size() >= 1) { // If there is more than one service with the same priority, @@ -2308,56 +2325,54 @@ class PackageManagerService extends IPackageManager.Stub { return null; } - public List queryIntentServices(Intent intent, - String resolvedType, int flags) { - ComponentName comp = intent.getComponent(); + public List queryIntentServices(Intent intent, String resolvedType, int flags) { + final ComponentName comp = intent.getComponent(); if (comp != null) { - List list = new ArrayList(1); - ServiceInfo si = getServiceInfo(comp, flags); + final List list = new ArrayList(1); + final ServiceInfo si = getServiceInfo(comp, flags); if (si != null) { - ResolveInfo ri = new ResolveInfo(); + final ResolveInfo ri = new ResolveInfo(); ri.serviceInfo = si; list.add(ri); } return list; } + // reader synchronized (mPackages) { String pkgName = intent.getPackage(); if (pkgName == null) { - return (List)mServices.queryIntent(intent, - resolvedType, flags); + return mServices.queryIntent(intent, resolvedType, flags); } - PackageParser.Package pkg = mPackages.get(pkgName); + final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { - return (List)mServices.queryIntentForPackage(intent, - resolvedType, flags, pkg.services); + return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services); } return null; } } public List getInstalledPackages(int flags) { - ArrayList finalList = new ArrayList(); + final ArrayList finalList = new ArrayList(); + // writer synchronized (mPackages) { if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { - Iterator i = mSettings.mPackages.values().iterator(); + final Iterator i = mSettings.mPackages.values().iterator(); while (i.hasNext()) { final PackageSetting ps = i.next(); - PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags); - if(psPkg != null) { + final PackageInfo psPkg = generatePackageInfoFromSettingsLPw(ps.name, flags); + if (psPkg != null) { finalList.add(psPkg); } } - } - else { - Iterator i = mPackages.values().iterator(); + } else { + final Iterator i = mPackages.values().iterator(); while (i.hasNext()) { final PackageParser.Package p = i.next(); if (p.applicationInfo != null) { - PackageInfo pi = generatePackageInfo(p, flags); - if(pi != null) { + final PackageInfo pi = generatePackageInfo(p, flags); + if (pi != null) { finalList.add(pi); } } @@ -2368,20 +2383,20 @@ class PackageManagerService extends IPackageManager.Stub { } public List getInstalledApplications(int flags) { - ArrayList finalList = new ArrayList(); + final ArrayList finalList = new ArrayList(); + // writer synchronized(mPackages) { if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { - Iterator i = mSettings.mPackages.values().iterator(); + final Iterator i = mSettings.mPackages.values().iterator(); while (i.hasNext()) { final PackageSetting ps = i.next(); - ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags); + ApplicationInfo ai = generateApplicationInfoFromSettingsLPw(ps.name, flags); if(ai != null) { finalList.add(ai); } } - } - else { - Iterator i = mPackages.values().iterator(); + } else { + final Iterator i = mPackages.values().iterator(); while (i.hasNext()) { final PackageParser.Package p = i.next(); if (p.applicationInfo != null) { @@ -2397,12 +2412,13 @@ class PackageManagerService extends IPackageManager.Stub { } public List getPersistentApplications(int flags) { - ArrayList finalList = new ArrayList(); + final ArrayList finalList = new ArrayList(); + // reader synchronized (mPackages) { - Iterator i = mPackages.values().iterator(); + final Iterator i = mPackages.values().iterator(); while (i.hasNext()) { - PackageParser.Package p = i.next(); + final PackageParser.Package p = i.next(); if (p.applicationInfo != null && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0 && (!mSafeMode || isSystemApp(p))) { @@ -2415,10 +2431,11 @@ class PackageManagerService extends IPackageManager.Stub { } public ProviderInfo resolveContentProvider(String name, int flags) { + // reader synchronized (mPackages) { final PackageParser.Provider provider = mProviders.get(name); return provider != null - && mSettings.isEnabledLP(provider.info, flags) + && mSettings.isEnabledLPr(provider.info, flags) && (!mSafeMode || (provider.info.applicationInfo.flags &ApplicationInfo.FLAG_SYSTEM) != 0) ? PackageParser.generateProviderInfo(provider, flags) @@ -2431,9 +2448,10 @@ class PackageManagerService extends IPackageManager.Stub { */ @Deprecated public void querySyncProviders(List outNames, List outInfo) { + // reader synchronized (mPackages) { - Iterator> i - = mProviders.entrySet().iterator(); + final Iterator> i = mProviders.entrySet() + .iterator(); while (i.hasNext()) { Map.Entry entry = i.next(); @@ -2453,22 +2471,22 @@ class PackageManagerService extends IPackageManager.Stub { int uid, int flags) { ArrayList finalList = null; + // reader synchronized (mPackages) { - Iterator i = mProvidersByComponent.values().iterator(); + final Iterator i = mProvidersByComponent.values().iterator(); while (i.hasNext()) { - PackageParser.Provider p = i.next(); + final PackageParser.Provider p = i.next(); if (p.info.authority != null - && (processName == null || - (p.info.processName.equals(processName) - && p.info.applicationInfo.uid == uid)) - && mSettings.isEnabledLP(p.info, flags) - && (!mSafeMode || (p.info.applicationInfo.flags - &ApplicationInfo.FLAG_SYSTEM) != 0)) { + && (processName == null + || (p.info.processName.equals(processName) + && p.info.applicationInfo.uid == uid)) + && mSettings.isEnabledLPr(p.info, flags) + && (!mSafeMode + || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) { if (finalList == null) { finalList = new ArrayList(3); } - finalList.add(PackageParser.generateProviderInfo(p, - flags)); + finalList.add(PackageParser.generateProviderInfo(p, flags)); } } } @@ -2482,6 +2500,7 @@ class PackageManagerService extends IPackageManager.Stub { public InstrumentationInfo getInstrumentationInfo(ComponentName name, int flags) { + // reader synchronized (mPackages) { final PackageParser.Instrumentation i = mInstrumentation.get(name); return PackageParser.generateInstrumentationInfo(i, flags); @@ -2493,10 +2512,11 @@ class PackageManagerService extends IPackageManager.Stub { ArrayList finalList = new ArrayList(); + // reader synchronized (mPackages) { - Iterator i = mInstrumentation.values().iterator(); + final Iterator i = mInstrumentation.values().iterator(); while (i.hasNext()) { - PackageParser.Instrumentation p = i.next(); + final PackageParser.Instrumentation p = i.next(); if (targetPackage == null || targetPackage.equals(p.info.targetPackage)) { finalList.add(PackageParser.generateInstrumentationInfo(p, @@ -2545,7 +2565,7 @@ class PackageManagerService extends IPackageManager.Stub { return fname; } - private static void reportSettingsProblem(int priority, String msg) { + static void reportSettingsProblem(int priority, String msg) { try { File fname = getSettingsProblemFile(); FileOutputStream out = new FileOutputStream(fname, true); @@ -2609,17 +2629,18 @@ class PackageManagerService extends IPackageManager.Stub { } PackageSetting ps = null; PackageSetting updatedPkg; + // reader synchronized (mPackages) { // Look to see if we already know about this package. String oldName = mSettings.mRenamedPackages.get(pkg.packageName); if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) { // This package has been renamed to its original name. Let's // use that. - ps = mSettings.peekPackageLP(oldName); + ps = mSettings.peekPackageLPr(oldName); } // If there was no original package, see one for the real package name. if (ps == null) { - ps = mSettings.peekPackageLP(pkg.packageName); + ps = mSettings.peekPackageLPr(pkg.packageName); } // Check to see if this package could be hiding/updating a system // package. Must look for it either under the original or real @@ -2648,6 +2669,7 @@ class PackageManagerService extends IPackageManager.Stub { // At this point, its safely assumed that package installation for // apps in system partition will go through. If not there won't be a working // version of the app + // writer synchronized (mPackages) { // Just remove the loaded entries from package lists. mPackages.remove(ps.name); @@ -2659,7 +2681,7 @@ class PackageManagerService extends IPackageManager.Stub { InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); args.cleanUpResourcesLI(); - mSettings.enableSystemPackageLP(ps.name); + mSettings.enableSystemPackageLPw(ps.name); } } } @@ -2717,7 +2739,7 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Package pkg) { if (pkgSetting.signatures.mSignatures != null) { // Already existing package. Make sure signatures match - if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) != + if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { Slog.e(TAG, "Package " + pkg.packageName + " signatures do not match the previously installed version; ignoring!"); @@ -2727,7 +2749,7 @@ class PackageManagerService extends IPackageManager.Stub { } // Check for shared user signatures if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) { - if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures, + if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { Slog.e(TAG, "Package " + pkg.packageName + " has no signatures that match those in shared user " @@ -2794,7 +2816,7 @@ class PackageManagerService extends IPackageManager.Stub { return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; } - private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) { + private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { Slog.w(TAG, "Unable to update from " + oldPkg.name + " to " + newPkg.packageName @@ -2895,6 +2917,7 @@ class PackageManagerService extends IPackageManager.Stub { pkg.mAdoptPermissions = null; } + // writer synchronized (mPackages) { // Check all shared libraries and map to their actual file path. if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) { @@ -2905,7 +2928,7 @@ class PackageManagerService extends IPackageManager.Stub { int num = 0; int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0; for (int i=0; i=0; i--) { - if ((origPackage=mSettings.peekPackageLP( + if ((origPackage = mSettings.peekPackageLPr( pkg.mOriginalPackages.get(i))) != null) { // We do have the package already installed under its // original name... should we use it? - if (!verifyPackageUpdate(origPackage, pkg)) { + if (!verifyPackageUpdateLPr(origPackage, pkg)) { // New package is not compatible with original. origPackage = null; continue; @@ -3008,7 +3031,7 @@ class PackageManagerService extends IPackageManager.Stub { // Just create the setting, don't add it yet. For already existing packages // the PkgSetting exists already and doesn't have to be created. - pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile, + pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.flags, true, false); if (pkgSetting == null) { @@ -3061,7 +3084,7 @@ class PackageManagerService extends IPackageManager.Stub { // associated with an overall shared user, which doesn't seem all // that unreasonable. if (pkgSetting.sharedUser != null) { - if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures, + if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser); mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; @@ -3100,25 +3123,25 @@ class PackageManagerService extends IPackageManager.Stub { } } } - } - final String pkgName = pkg.packageName; - - if (pkg.mAdoptPermissions != null) { - // This package wants to adopt ownership of permissions from - // another package. - for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) { - String origName = pkg.mAdoptPermissions.get(i); - PackageSetting orig = mSettings.peekPackageLP(origName); - if (orig != null) { - if (verifyPackageUpdate(orig, pkg)) { - Slog.i(TAG, "Adopting permissions from " - + origName + " to " + pkg.packageName); - mSettings.transferPermissions(origName, pkg.packageName); + if (pkg.mAdoptPermissions != null) { + // This package wants to adopt ownership of permissions from + // another package. + for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) { + final String origName = pkg.mAdoptPermissions.get(i); + final PackageSetting orig = mSettings.peekPackageLPr(origName); + if (orig != null) { + if (verifyPackageUpdateLPr(orig, pkg)) { + Slog.i(TAG, "Adopting permissions from " + origName + " to " + + pkg.packageName); + mSettings.transferPermissionsLPw(origName, pkg.packageName); + } } } } } + + final String pkgName = pkg.packageName; final long scanFileTime = scanFile.lastModified(); final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0; @@ -3186,6 +3209,7 @@ class PackageManagerService extends IPackageManager.Stub { + " has mismatched uid: " + mOutPermissions[1] + " on disk, " + pkg.applicationInfo.uid + " in settings"; + // writer synchronized (mPackages) { mSettings.mReadMessages.append(msg); mSettings.mReadMessages.append('\n'); @@ -3319,13 +3343,14 @@ class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.uid); } + // writer synchronized (mPackages) { // We don't expect installation to fail beyond this point, if ((scanMode&SCAN_MONITOR) != 0) { mAppDirs.put(pkg.mPath, pkg); } // Add the new setting to mSettings - mSettings.insertPackageSettingLP(pkgSetting, pkg); + mSettings.insertPackageSettingLPw(pkgSetting, pkg); // Add the new setting to mPackages mPackages.put(pkg.applicationInfo.packageName, pkg); // Make sure we don't accidentally delete its data. @@ -3624,8 +3649,9 @@ class PackageManagerService extends IPackageManager.Stub { Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName); } + // writer synchronized (mPackages) { - clearPackagePreferredActivitiesLP(pkg.packageName); + clearPackagePreferredActivitiesLPw(pkg.packageName); mPackages.remove(pkg.applicationInfo.packageName); if (pkg.mPath != null) { @@ -3783,14 +3809,13 @@ class PackageManagerService extends IPackageManager.Stub { return false; } - private void updatePermissionsLP(String changingPkg, + private void updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo, boolean grantPermissions, boolean replace, boolean replaceAll) { // Make sure there are no dangling permission trees. - Iterator it = mSettings.mPermissionTrees - .values().iterator(); + Iterator it = mSettings.mPermissionTrees.values().iterator(); while (it.hasNext()) { - BasePermission bp = it.next(); + final BasePermission bp = it.next(); if (bp.packageSetting == null) { // We may not yet have parsed the package, so just see if // we still know about its settings. @@ -3814,13 +3839,13 @@ class PackageManagerService extends IPackageManager.Stub { // and make sure there are no dangling permissions. it = mSettings.mPermissions.values().iterator(); while (it.hasNext()) { - BasePermission bp = it.next(); + final BasePermission bp = it.next(); if (bp.type == BasePermission.TYPE_DYNAMIC) { if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name=" + bp.name + " pkg=" + bp.sourcePackage + " info=" + bp.pendingInfo); if (bp.packageSetting == null && bp.pendingInfo != null) { - BasePermission tree = findPermissionTreeLP(bp.name); + final BasePermission tree = findPermissionTreeLP(bp.name); if (tree != null) { bp.packageSetting = tree.packageSetting; bp.perm = new PackageParser.Permission(tree.perm.owner, @@ -3855,18 +3880,18 @@ class PackageManagerService extends IPackageManager.Stub { if (grantPermissions) { for (PackageParser.Package pkg : mPackages.values()) { if (pkg != pkgInfo) { - grantPermissionsLP(pkg, replaceAll); + grantPermissionsLPw(pkg, replaceAll); } } } if (pkgInfo != null) { - grantPermissionsLP(pkgInfo, replace); + grantPermissionsLPw(pkgInfo, replace); } } - private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) { - final PackageSetting ps = (PackageSetting)pkg.mExtras; + private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) { + final PackageSetting ps = (PackageSetting) pkg.mExtras; if (ps == null) { return; } @@ -3887,8 +3912,8 @@ class PackageManagerService extends IPackageManager.Stub { final int N = pkg.requestedPermissions.size(); for (int i=0; i 0, false, false); } addedPackage = p.applicationInfo.packageName; @@ -4531,8 +4566,9 @@ class PackageManagerService extends IPackageManager.Stub { } } + // reader synchronized (mPackages) { - mSettings.writeLP(); + mSettings.writeLPr(); } } @@ -4582,6 +4618,7 @@ class PackageManagerService extends IPackageManager.Stub { public void setInstallerPackageName(String targetPackage, String installerPackageName) { final int uid = Binder.getCallingUid(); + // writer synchronized (mPackages) { PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage); if (targetPackageSetting == null) { @@ -4600,7 +4637,7 @@ class PackageManagerService extends IPackageManager.Stub { } Signature[] callerSignature; - Object obj = mSettings.getUserIdLP(uid); + Object obj = mSettings.getUserIdLPr(uid); if (obj != null) { if (obj instanceof SharedUserSetting) { callerSignature = ((SharedUserSetting)obj).signatures.mSignatures; @@ -4616,7 +4653,7 @@ class PackageManagerService extends IPackageManager.Stub { // Verify: can't set installerPackageName to a package that is // not signed with the same cert as the caller. if (installerPackageSetting != null) { - if (checkSignaturesLP(callerSignature, + if (compareSignatures(callerSignature, installerPackageSetting.signatures.mSignatures) != PackageManager.SIGNATURE_MATCH) { throw new SecurityException( @@ -4633,7 +4670,7 @@ class PackageManagerService extends IPackageManager.Stub { // If the currently set package isn't valid, then it's always // okay to change it. if (setting != null) { - if (checkSignaturesLP(callerSignature, + if (compareSignatures(callerSignature, setting.signatures.mSignatures) != PackageManager.SIGNATURE_MATCH) { throw new SecurityException( @@ -4849,6 +4886,7 @@ class PackageManagerService extends IPackageManager.Stub { String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; + // reader synchronized (mPackages) { PackageParser.Package pkg = mPackages.get(packageName); if (pkg != null) { @@ -5719,7 +5757,7 @@ class PackageManagerService extends IPackageManager.Stub { // First find the old package info and check signatures synchronized(mPackages) { oldPackage = mPackages.get(pkgName); - if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures) + if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; return; @@ -5805,10 +5843,12 @@ class PackageManagerService extends IPackageManager.Stub { return; } // Restore of old package succeeded. Update permissions. + // writer synchronized (mPackages) { - updatePermissionsLP(deletedPackage.packageName, deletedPackage, + updatePermissionsLPw(deletedPackage.packageName, deletedPackage, true, false, false); - mSettings.writeLP(); + // can downgrade to reader + mSettings.writeLPr(); } Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade"); } @@ -5831,6 +5871,7 @@ class PackageManagerService extends IPackageManager.Stub { } PackageParser.Package oldPkg; PackageSetting oldPkgSetting; + // reader synchronized (mPackages) { oldPkg = mPackages.get(packageName); oldPkgSetting = mSettings.mPackages.get(packageName); @@ -5847,8 +5888,9 @@ class PackageManagerService extends IPackageManager.Stub { res.removedInfo.removedPackage = packageName; // Remove existing system package removePackageLI(oldPkg, true); + // writer synchronized (mPackages) { - if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) { + if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) { // We didn't need to disable the .apk as a current system package, // which means we are replacing another update that is already // installed. We need to make sure to delete the older one's .apk. @@ -5892,11 +5934,11 @@ class PackageManagerService extends IPackageManager.Stub { // Restore the old system information in Settings synchronized(mPackages) { if (updatedSettings) { - mSettings.enableSystemPackageLP(packageName); + mSettings.enableSystemPackageLPw(packageName); mSettings.setInstallerPackageName(packageName, oldPkgSetting.installerPackageName); } - mSettings.writeLP(); + mSettings.writeLPr(); } } } @@ -5930,8 +5972,8 @@ class PackageManagerService extends IPackageManager.Stub { //write settings. the installStatus will be incomplete at this stage. //note that the new package setting would have already been //added to mPackages. It hasn't been persisted yet. - mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE); - mSettings.writeLP(); + mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE); + mSettings.writeLPr(); } if ((res.returnCode = moveDexFilesLI(newPackage)) @@ -5949,16 +5991,16 @@ class PackageManagerService extends IPackageManager.Stub { Log.d(TAG, "New package installed in " + newPackage.mPath); } synchronized (mPackages) { - updatePermissionsLP(newPackage.packageName, newPackage, + updatePermissionsLPw(newPackage.packageName, newPackage, newPackage.permissions.size() > 0, true, false); res.name = pkgName; res.uid = newPackage.applicationInfo.uid; res.pkg = newPackage; - mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE); + mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE); mSettings.setInstallerPackageName(pkgName, installerPackageName); res.returnCode = PackageManager.INSTALL_SUCCEEDED; //to update install status - mSettings.writeLP(); + mSettings.writeLPr(); } } @@ -6336,7 +6378,8 @@ class PackageManagerService extends IPackageManager.Stub { } removePackageLI(p, (flags&REMOVE_CHATTY) != 0); // Retrieve object to delete permissions for shared user later on - PackageSetting deletedPs; + final PackageSetting deletedPs; + // reader synchronized (mPackages) { deletedPs = mSettings.mPackages.get(packageName); } @@ -6350,23 +6393,28 @@ class PackageManagerService extends IPackageManager.Stub { } } else { // for simulator - PackageParser.Package pkg = mPackages.get(packageName); - File dataDir = new File(pkg.applicationInfo.dataDir); + File dataDir; + // reader + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(packageName); + dataDir = new File(pkg.applicationInfo.dataDir); + } dataDir.delete(); } schedulePackageCleaning(packageName); } + // writer synchronized (mPackages) { if (deletedPs != null) { if ((flags&PackageManager.DONT_DELETE_DATA) == 0) { if (outInfo != null) { - outInfo.removedUid = mSettings.removePackageLP(packageName); + outInfo.removedUid = mSettings.removePackageLPw(packageName); } if (deletedPs != null) { - updatePermissionsLP(deletedPs.name, null, false, false, false); + updatePermissionsLPw(deletedPs.name, null, false, false, false); if (deletedPs.sharedUser != null) { // remove permissions associated with package - mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids); + mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids); } } } @@ -6381,9 +6429,10 @@ class PackageManagerService extends IPackageManager.Stub { mSettings.mPreferredActivities.removeFilter(pa); } } + // can downgrade to reader if (writeSettings) { // Save settings now - mSettings.writeLP(); + mSettings.writeLPr(); } } } @@ -6403,8 +6452,9 @@ class PackageManagerService extends IPackageManager.Stub { // Confirm if the system package has been updated // An updated system app can be deleted. This will also have to restore // the system pkg from system partition + // reader synchronized (mPackages) { - ps = mSettings.getDisabledSystemPkg(p.packageName); + ps = mSettings.getDisabledSystemPkgLPr(p.packageName); } if (ps == null) { Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName); @@ -6426,9 +6476,10 @@ class PackageManagerService extends IPackageManager.Stub { if (!ret) { return false; } + // writer synchronized (mPackages) { // Reinstate the old system package - mSettings.enableSystemPackageLP(p.packageName); + mSettings.enableSystemPackageLPw(p.packageName); // Remove any native libraries from the upgraded package. NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir); } @@ -6441,10 +6492,12 @@ class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError); return false; } + // writer synchronized (mPackages) { - updatePermissionsLP(newPkg.packageName, newPkg, true, true, false); + updatePermissionsLPw(newPkg.packageName, newPkg, true, true, false); + // can downgrade to reader here if (writeSettings) { - mSettings.writeLP(); + mSettings.writeLPr(); } } return true; @@ -6732,14 +6785,14 @@ class PackageManagerService extends IPackageManager.Stub { return new ArrayList(); } - private int getUidTargetSdkVersionLockedLP(int uid) { - Object obj = mSettings.getUserIdLP(uid); + private int getUidTargetSdkVersionLockedLPr(int uid) { + Object obj = mSettings.getUserIdLPr(uid); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; int vers = Build.VERSION_CODES.CUR_DEVELOPMENT; final Iterator it = sus.packages.iterator(); while (it.hasNext()) { - PackageSetting ps = it.next(); + final PackageSetting ps = it.next(); if (ps.pkg != null) { int v = ps.pkg.applicationInfo.targetSdkVersion; if (v < vers) vers = v; @@ -6757,11 +6810,12 @@ class PackageManagerService extends IPackageManager.Stub { public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { + // writer synchronized (mPackages) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) + if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid()) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring addPreferredActivity() from uid " + Binder.getCallingUid()); @@ -6801,7 +6855,7 @@ class PackageManagerService extends IPackageManager.Stub { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) + if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid()) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring replacePreferredActivity() from uid " + Binder.getCallingUid()); @@ -6827,14 +6881,15 @@ class PackageManagerService extends IPackageManager.Stub { } public void clearPackagePreferredActivities(String packageName) { + final int uid = Binder.getCallingUid(); + // writer synchronized (mPackages) { - int uid = Binder.getCallingUid(); PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null || pkg.applicationInfo.uid != uid) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) + if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid()) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid " + Binder.getCallingUid()); @@ -6845,13 +6900,13 @@ class PackageManagerService extends IPackageManager.Stub { } } - if (clearPackagePreferredActivitiesLP(packageName)) { + if (clearPackagePreferredActivitiesLPw(packageName)) { scheduleWriteSettingsLocked(); } } } - boolean clearPackagePreferredActivitiesLP(String packageName) { + boolean clearPackagePreferredActivitiesLPw(String packageName) { boolean changed = false; Iterator it = mSettings.mPreferredActivities.filterIterator(); while (it.hasNext()) { @@ -6868,10 +6923,11 @@ class PackageManagerService extends IPackageManager.Stub { List outActivities, String packageName) { int num = 0; + // reader synchronized (mPackages) { - Iterator it = mSettings.mPreferredActivities.filterIterator(); + final Iterator it = mSettings.mPreferredActivities.filterIterator(); while (it.hasNext()) { - PreferredActivity pa = it.next(); + final PreferredActivity pa = it.next(); if (packageName == null || pa.mPref.mComponent.getPackageName().equals(packageName)) { if (outFilters != null) { @@ -6916,6 +6972,8 @@ class PackageManagerService extends IPackageManager.Stub { String componentName = isApp ? packageName : className; int packageUid = -1; ArrayList components; + + // writer synchronized (mPackages) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null) { @@ -6945,17 +7003,17 @@ class PackageManagerService extends IPackageManager.Stub { // We're dealing with a component level state change switch (newState) { case COMPONENT_ENABLED_STATE_ENABLED: - if (!pkgSetting.enableComponentLP(className)) { + if (!pkgSetting.enableComponentLPw(className)) { return; } break; case COMPONENT_ENABLED_STATE_DISABLED: - if (!pkgSetting.disableComponentLP(className)) { + if (!pkgSetting.disableComponentLPw(className)) { return; } break; case COMPONENT_ENABLED_STATE_DEFAULT: - if (!pkgSetting.restoreComponentLP(className)) { + if (!pkgSetting.restoreComponentLPw(className)) { return; } break; @@ -6964,10 +7022,10 @@ class PackageManagerService extends IPackageManager.Stub { return; } } - mSettings.writeLP(); + mSettings.writeLPr(); packageUid = pkgSetting.userId; components = mPendingBroadcasts.get(packageName); - boolean newPackage = components == null; + final boolean newPackage = components == null; if (newPackage) { components = new ArrayList(); } @@ -7017,72 +7075,37 @@ class PackageManagerService extends IPackageManager.Stub { } public void setPackageStoppedState(String packageName, boolean stopped) { - PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); + // writer synchronized (mPackages) { - pkgSetting = mSettings.mPackages.get(packageName); - if (pkgSetting == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - if (!allowedByPermission && (uid != pkgSetting.userId)) { - throw new SecurityException( - "Permission Denial: attempt to change stopped state from pid=" - + Binder.getCallingPid() - + ", uid=" + uid + ", package uid=" + pkgSetting.userId); - } - if (DEBUG_STOPPED && stopped) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Slog.i(TAG, "Stopping package " + packageName, e); - } - if (pkgSetting.stopped != stopped) { - pkgSetting.stopped = stopped; - pkgSetting.pkg.mSetStopped = stopped; - if (pkgSetting.notLaunched) { - if (pkgSetting.installerPackageName != null) { - sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, - pkgSetting.name, null, - pkgSetting.installerPackageName, null); - } - pkgSetting.notLaunched = false; - } + if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission, + uid)) { scheduleWriteStoppedPackagesLocked(); } } } public String getInstallerPackageName(String packageName) { + // reader synchronized (mPackages) { - PackageSetting pkg = mSettings.mPackages.get(packageName); - if (pkg == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - return pkg.installerPackageName; + return mSettings.getInstallerPackageNameLPr(packageName); } } - public int getApplicationEnabledSetting(String appPackageName) { + public int getApplicationEnabledSetting(String packageName) { + // reader synchronized (mPackages) { - PackageSetting pkg = mSettings.mPackages.get(appPackageName); - if (pkg == null) { - throw new IllegalArgumentException("Unknown package: " + appPackageName); - } - return pkg.enabled; + return mSettings.getApplicationEnabledSettingLPr(packageName); } } public int getComponentEnabledSetting(ComponentName componentName) { + // reader synchronized (mPackages) { - final String packageNameStr = componentName.getPackageName(); - PackageSetting pkg = mSettings.mPackages.get(packageNameStr); - if (pkg == null) { - throw new IllegalArgumentException("Unknown component: " + componentName); - } - final String classNameStr = componentName.getClassName(); - return pkg.currentEnabledStateLP(classNameStr); + return mSettings.getComponentEnabledSettingLPr(componentName); } } @@ -7126,6 +7149,76 @@ class PackageManagerService extends IPackageManager.Stub { return buf.toString(); } + static class DumpState { + public static final int DUMP_LIBS = 1 << 0; + + public static final int DUMP_FEATURES = 1 << 1; + + public static final int DUMP_RESOLVERS = 1 << 2; + + public static final int DUMP_PERMISSIONS = 1 << 3; + + public static final int DUMP_PACKAGES = 1 << 4; + + public static final int DUMP_SHARED_USERS = 1 << 5; + + public static final int DUMP_MESSAGES = 1 << 6; + + public static final int DUMP_PROVIDERS = 1 << 7; + + public static final int OPTION_SHOW_FILTERS = 1 << 0; + + private int mTypes; + + private int mOptions; + + private boolean mTitlePrinted; + + private SharedUserSetting mSharedUser; + + public boolean isDumping(int type) { + if (mTypes == 0) { + return true; + } + + return (mTypes & type) != 0; + } + + public void setDump(int type) { + mTypes |= type; + } + + public boolean isOptionEnabled(int option) { + return (mOptions & option) != 0; + } + + public void setOptionEnabled(int option) { + mOptions |= option; + } + + public boolean onTitlePrinted() { + final boolean printed = mTitlePrinted; + mTitlePrinted = true; + return printed; + } + + public boolean getTitlePrinted() { + return mTitlePrinted; + } + + public void setTitlePrinted(boolean enabled) { + mTitlePrinted = enabled; + } + + public SharedUserSetting getSharedUser() { + return mSharedUser; + } + + public void setSharedUser(SharedUserSetting user) { + mSharedUser = user; + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -7138,18 +7231,9 @@ class PackageManagerService extends IPackageManager.Stub { return; } - boolean dumpStar = true; - boolean dumpLibs = false; - boolean dumpFeatures = false; - boolean dumpResolvers = false; - boolean dumpPermissions = false; - boolean dumpPackages = false; - boolean dumpSharedUsers = false; - boolean dumpMessages = false; - boolean dumpProviders = false; + DumpState dumpState = new DumpState(); String packageName = null; - boolean showFilters = false; int opti = 0; while (opti < args.length) { @@ -7177,7 +7261,7 @@ class PackageManagerService extends IPackageManager.Stub { pw.println(" : info about given package"); return; } else if ("-f".equals(opt)) { - showFilters = true; + dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS); } else { pw.println("Unknown argument: " + opt + "; use -h for help"); } @@ -7191,40 +7275,31 @@ class PackageManagerService extends IPackageManager.Stub { if ("android".equals(cmd) || cmd.contains(".")) { packageName = cmd; } else if ("l".equals(cmd) || "libraries".equals(cmd)) { - dumpStar = false; - dumpLibs = true; + dumpState.setDump(DumpState.DUMP_LIBS); } else if ("f".equals(cmd) || "features".equals(cmd)) { - dumpStar = false; - dumpFeatures = true; + dumpState.setDump(DumpState.DUMP_FEATURES); } else if ("r".equals(cmd) || "resolvers".equals(cmd)) { - dumpStar = false; - dumpResolvers = true; + dumpState.setDump(DumpState.DUMP_RESOLVERS); } else if ("perm".equals(cmd) || "permissions".equals(cmd)) { - dumpStar = false; - dumpPermissions = true; + dumpState.setDump(DumpState.DUMP_PERMISSIONS); } else if ("p".equals(cmd) || "packages".equals(cmd)) { - dumpStar = false; - dumpPackages = true; + dumpState.setDump(DumpState.DUMP_PACKAGES); } else if ("s".equals(cmd) || "shared-users".equals(cmd)) { - dumpStar = false; - dumpSharedUsers = true; + dumpState.setDump(DumpState.DUMP_SHARED_USERS); } else if ("prov".equals(cmd) || "providers".equals(cmd)) { - dumpStar = false; - dumpProviders = true; + dumpState.setDump(DumpState.DUMP_PROVIDERS); } else if ("m".equals(cmd) || "messages".equals(cmd)) { - dumpStar = false; - dumpMessages = true; + dumpState.setDump(DumpState.DUMP_MESSAGES); } } - - boolean printedTitle = false; - + + // reader synchronized (mPackages) { - if ((dumpStar || dumpLibs) && packageName == null) { - if (printedTitle) pw.println(" "); - printedTitle = true; + if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) { + if (dumpState.onTitlePrinted()) + pw.println(" "); pw.println("Libraries:"); - Iterator it = mSharedLibraries.keySet().iterator(); + final Iterator it = mSharedLibraries.keySet().iterator(); while (it.hasNext()) { String name = it.next(); pw.print(" "); @@ -7234,9 +7309,9 @@ class PackageManagerService extends IPackageManager.Stub { } } - if ((dumpStar || dumpFeatures) && packageName == null) { - if (printedTitle) pw.println(" "); - printedTitle = true; + if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) { + if (dumpState.onTitlePrinted()) + pw.println(" "); pw.println("Features:"); Iterator it = mAvailableFeatures.keySet().iterator(); while (it.hasNext()) { @@ -7246,276 +7321,72 @@ class PackageManagerService extends IPackageManager.Stub { } } - if (dumpStar || dumpResolvers) { - if (mActivities.dump(pw, printedTitle - ? "\nActivity Resolver Table:" : "Activity Resolver Table:", - " ", packageName, showFilters)) { - printedTitle = true; + if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) { + if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:" + : "Activity Resolver Table:", " ", packageName, + dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) { + dumpState.setTitlePrinted(true); } - if (mReceivers.dump(pw, printedTitle - ? "\nReceiver Resolver Table:" : "Receiver Resolver Table:", - " ", packageName, showFilters)) { - printedTitle = true; + if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:" + : "Receiver Resolver Table:", " ", packageName, + dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) { + dumpState.setTitlePrinted(true); } - if (mServices.dump(pw, printedTitle - ? "\nService Resolver Table:" : "Service Resolver Table:", - " ", packageName, showFilters)) { - printedTitle = true; + if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:" + : "Service Resolver Table:", " ", packageName, + dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) { + dumpState.setTitlePrinted(true); } - if (mSettings.mPreferredActivities.dump(pw, printedTitle - ? "\nPreferred Activities:" : "Preferred Activities:", - " ", packageName, showFilters)) { - printedTitle = true; + if (mSettings.mPreferredActivities.dump(pw, + dumpState.getTitlePrinted() ? "\nPreferred Activities:" + : "Preferred Activities:", " ", + packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) { + dumpState.setTitlePrinted(true); } } - boolean printedSomething = false; - if (dumpStar || dumpPermissions) { - for (BasePermission p : mSettings.mPermissions.values()) { - if (packageName != null && !packageName.equals(p.sourcePackage)) { - continue; - } - if (!printedSomething) { - if (printedTitle) pw.println(" "); - pw.println("Permissions:"); - printedSomething = true; - printedTitle = true; - } - pw.print(" Permission ["); pw.print(p.name); pw.print("] ("); - pw.print(Integer.toHexString(System.identityHashCode(p))); - pw.println("):"); - pw.print(" sourcePackage="); pw.println(p.sourcePackage); - pw.print(" uid="); pw.print(p.uid); - pw.print(" gids="); pw.print(arrayToString(p.gids)); - pw.print(" type="); pw.print(p.type); - pw.print(" prot="); pw.println(p.protectionLevel); - if (p.packageSetting != null) { - pw.print(" packageSetting="); pw.println(p.packageSetting); - } - if (p.perm != null) { - pw.print(" perm="); pw.println(p.perm); - } - } + if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) { + mSettings.dumpPermissionsLPr(pw, packageName, dumpState); } - if (dumpStar || dumpProviders) { - printedSomething = false; + if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) { + boolean printedSomething = false; for (PackageParser.Provider p : mProviders.values()) { if (packageName != null && !packageName.equals(p.info.packageName)) { continue; } if (!printedSomething) { - if (printedTitle) pw.println(" "); + if (dumpState.onTitlePrinted()) + pw.println(" "); pw.println("Registered ContentProviders:"); printedSomething = true; - printedTitle = true; } pw.print(" ["); pw.print(p.info.authority); pw.print("]: "); pw.println(p.toString()); } } - printedSomething = false; - SharedUserSetting packageSharedUser = null; - if (dumpStar || dumpPackages) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Date date = new Date(); - for (PackageSetting ps : mSettings.mPackages.values()) { - if (packageName != null && !packageName.equals(ps.realName) - && !packageName.equals(ps.name)) { - continue; - } - if (!printedSomething) { - if (printedTitle) pw.println(" "); - pw.println("Packages:"); - printedSomething = true; - printedTitle = true; - } - packageSharedUser = ps.sharedUser; - pw.print(" Package ["); - pw.print(ps.realName != null ? ps.realName : ps.name); - pw.print("] ("); - pw.print(Integer.toHexString(System.identityHashCode(ps))); - pw.println("):"); - if (ps.realName != null) { - pw.print(" compat name="); pw.println(ps.name); - } - pw.print(" userId="); pw.print(ps.userId); - pw.print(" gids="); pw.println(arrayToString(ps.gids)); - pw.print(" sharedUser="); pw.println(ps.sharedUser); - pw.print(" pkg="); pw.println(ps.pkg); - pw.print(" codePath="); pw.println(ps.codePathString); - pw.print(" resourcePath="); pw.println(ps.resourcePathString); - pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString); - pw.print(" versionCode="); pw.println(ps.versionCode); - if (ps.pkg != null) { - pw.print(" versionName="); pw.println(ps.pkg.mVersionName); - pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); - pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion); - if (ps.pkg.mOperationPending) { - pw.println(" mOperationPending=true"); - } - pw.print(" supportsScreens=["); - boolean first = true; - if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { - if (!first) pw.print(", "); - first = false; - pw.print("small"); - } - if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { - if (!first) pw.print(", "); - first = false; - pw.print("medium"); - } - if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { - if (!first) pw.print(", "); - first = false; - pw.print("large"); - } - if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { - if (!first) pw.print(", "); - first = false; - pw.print("xlarge"); - } - if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { - if (!first) pw.print(", "); - first = false; - pw.print("resizeable"); - } - if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { - if (!first) pw.print(", "); - first = false; - pw.print("anyDensity"); - } - } - pw.println("]"); - pw.print(" timeStamp="); - date.setTime(ps.timeStamp); pw.println(sdf.format(date)); - pw.print(" firstInstallTime="); - date.setTime(ps.firstInstallTime); pw.println(sdf.format(date)); - pw.print(" lastUpdateTime="); - date.setTime(ps.lastUpdateTime); pw.println(sdf.format(date)); - if (ps.installerPackageName != null) { - pw.print(" installerPackageName="); pw.println(ps.installerPackageName); - } - pw.print(" signatures="); pw.println(ps.signatures); - pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed); - pw.print(" haveGids="); pw.println(ps.haveGids); - pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags)); - pw.print(" installStatus="); pw.print(ps.installStatus); - pw.print(" stopped="); pw.print(ps.stopped); - pw.print(" enabled="); pw.println(ps.enabled); - if (ps.disabledComponents.size() > 0) { - pw.println(" disabledComponents:"); - for (String s : ps.disabledComponents) { - pw.print(" "); pw.println(s); - } - } - if (ps.enabledComponents.size() > 0) { - pw.println(" enabledComponents:"); - for (String s : ps.enabledComponents) { - pw.print(" "); pw.println(s); - } - } - if (ps.grantedPermissions.size() > 0) { - pw.println(" grantedPermissions:"); - for (String s : ps.grantedPermissions) { - pw.print(" "); pw.println(s); - } - } - } + if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) { + mSettings.dumpPackagesLPr(pw, packageName, dumpState); } - printedSomething = false; - if (dumpStar || dumpPackages) { - if (mSettings.mRenamedPackages.size() > 0) { - for (HashMap.Entry e - : mSettings.mRenamedPackages.entrySet()) { - if (packageName != null && !packageName.equals(e.getKey()) - && !packageName.equals(e.getValue())) { - continue; - } - if (!printedSomething) { - if (printedTitle) pw.println(" "); - pw.println("Renamed packages:"); - printedSomething = true; - printedTitle = true; - } - pw.print(" "); pw.print(e.getKey()); pw.print(" -> "); - pw.println(e.getValue()); - } - } - printedSomething = false; - if (mSettings.mDisabledSysPackages.size() > 0) { - for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) { - if (packageName != null && !packageName.equals(ps.realName) - && !packageName.equals(ps.name)) { - continue; - } - if (!printedSomething) { - if (printedTitle) pw.println(" "); - pw.println("Hidden system packages:"); - printedSomething = true; - printedTitle = true; - } - pw.print(" Package ["); - pw.print(ps.realName != null ? ps.realName : ps.name); - pw.print("] ("); - pw.print(Integer.toHexString(System.identityHashCode(ps))); - pw.println("):"); - if (ps.realName != null) { - pw.print(" compat name="); pw.println(ps.name); - } - pw.print(" userId="); pw.println(ps.userId); - pw.print(" sharedUser="); pw.println(ps.sharedUser); - pw.print(" codePath="); pw.println(ps.codePathString); - pw.print(" resourcePath="); pw.println(ps.resourcePathString); - } - } + + if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) { + mSettings.dumpSharedUsersLPr(pw, packageName, dumpState); } - printedSomething = false; - if (dumpStar || dumpSharedUsers) { - for (SharedUserSetting su : mSettings.mSharedUsers.values()) { - if (packageName != null && su != packageSharedUser) { - continue; - } - if (!printedSomething) { - if (printedTitle) pw.println(" "); - pw.println("Shared users:"); - printedSomething = true; - printedTitle = true; - } - pw.print(" SharedUser ["); pw.print(su.name); pw.print("] ("); - pw.print(Integer.toHexString(System.identityHashCode(su))); - pw.println("):"); - pw.print(" userId="); pw.print(su.userId); - pw.print(" gids="); pw.println(arrayToString(su.gids)); - pw.println(" grantedPermissions:"); - for (String s : su.grantedPermissions) { - pw.print(" "); pw.println(s); - } - } - } - - if ((dumpStar || dumpMessages) && packageName == null) { - if (printedTitle) pw.println(" "); - printedTitle = true; - pw.println("Settings parse messages:"); - pw.print(mSettings.mReadMessages.toString()); - + + if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + mSettings.dumpReadMessagesLPr(pw, dumpState); + pw.println(" "); pw.println("Package warning messages:"); - File fname = getSettingsProblemFile(); + final File fname = getSettingsProblemFile(); FileInputStream in = null; try { in = new FileInputStream(fname); - int avail = in.available(); - byte[] data = new byte[avail]; + final int avail = in.available(); + final byte[] data = new byte[avail]; in.read(data); pw.print(new String(data)); } catch (FileNotFoundException e) { @@ -7524,7 +7395,7 @@ class PackageManagerService extends IPackageManager.Stub { if (in != null) { try { in.close(); - } catch (IOException e) { + } catch (IOException e) { } } } @@ -7532,2411 +7403,13 @@ class PackageManagerService extends IPackageManager.Stub { } } - static final class BasePermission { - final static int TYPE_NORMAL = 0; - final static int TYPE_BUILTIN = 1; - final static int TYPE_DYNAMIC = 2; - - final String name; - String sourcePackage; - PackageSettingBase packageSetting; - final int type; - int protectionLevel; - PackageParser.Permission perm; - PermissionInfo pendingInfo; - int uid; - int[] gids; - - BasePermission(String _name, String _sourcePackage, int _type) { - name = _name; - sourcePackage = _sourcePackage; - type = _type; - // Default to most conservative protection level. - protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; - } - - public String toString() { - return "BasePermission{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "}"; - } - } - - static class PackageSignatures { - private Signature[] mSignatures; - - PackageSignatures(PackageSignatures orig) { - if (orig != null && orig.mSignatures != null) { - mSignatures = orig.mSignatures.clone(); - } - } - - PackageSignatures(Signature[] sigs) { - assignSignatures(sigs); - } - - PackageSignatures() { - } - - void writeXml(XmlSerializer serializer, String tagName, - ArrayList pastSignatures) throws IOException { - if (mSignatures == null) { - return; - } - serializer.startTag(null, tagName); - serializer.attribute(null, "count", - Integer.toString(mSignatures.length)); - for (int i=0; i= numPast) { - pastSignatures.add(sig); - serializer.attribute(null, "index", Integer.toString(numPast)); - serializer.attribute(null, "key", sig.toCharsString()); - } - serializer.endTag(null, "cert"); - } - serializer.endTag(null, tagName); - } - - void readXml(XmlPullParser parser, ArrayList pastSignatures) - throws IOException, XmlPullParserException { - String countStr = parser.getAttributeValue(null, "count"); - if (countStr == null) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has" - + " no count at " + parser.getPositionDescription()); - XmlUtils.skipCurrentTag(parser); - } - final int count = Integer.parseInt(countStr); - mSignatures = new Signature[count]; - int pos = 0; - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("cert")) { - if (pos < count) { - String index = parser.getAttributeValue(null, "index"); - if (index != null) { - try { - int idx = Integer.parseInt(index); - String key = parser.getAttributeValue(null, "key"); - if (key == null) { - if (idx >= 0 && idx < pastSignatures.size()) { - Signature sig = pastSignatures.get(idx); - if (sig != null) { - mSignatures[pos] = pastSignatures.get(idx); - pos++; - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: " - + "index " + index + " is not defined at " - + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: " - + "index " + index + " is out of bounds at " - + parser.getPositionDescription()); - } - } else { - while (pastSignatures.size() <= idx) { - pastSignatures.add(null); - } - Signature sig = new Signature(key); - pastSignatures.set(idx, sig); - mSignatures[pos] = sig; - pos++; - } - } catch (NumberFormatException e) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: " - + "index " + index + " is not a number at " - + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has" - + " no index at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: too " - + "many tags, expected " + count - + " at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - } - XmlUtils.skipCurrentTag(parser); - } - - if (pos < count) { - // Should never happen -- there is an error in the written - // settings -- but if it does we don't want to generate - // a bad array. - Signature[] newSigs = new Signature[pos]; - System.arraycopy(mSignatures, 0, newSigs, 0, pos); - mSignatures = newSigs; - } - } - - private void assignSignatures(Signature[] sigs) { - if (sigs == null) { - mSignatures = null; - return; - } - mSignatures = new Signature[sigs.length]; - for (int i=0; i 0) buf.append(", "); - buf.append(Integer.toHexString( - System.identityHashCode(mSignatures[i]))); - } - } - buf.append("]}"); - return buf.toString(); - } - } - - static class PreferredActivity extends IntentFilter implements PreferredComponent.Callbacks { - final PreferredComponent mPref; - - PreferredActivity(IntentFilter filter, int match, ComponentName[] set, - ComponentName activity) { - super(filter); - mPref = new PreferredComponent(this, match, set, activity); - } - - PreferredActivity(XmlPullParser parser) throws XmlPullParserException, - IOException { - mPref = new PreferredComponent(this, parser); - } - - public void writeToXml(XmlSerializer serializer) throws IOException { - mPref.writeToXml(serializer); - serializer.startTag(null, "filter"); - super.writeToXml(serializer); - serializer.endTag(null, "filter"); - } - - public boolean onReadTag(String tagName, XmlPullParser parser) - throws XmlPullParserException, IOException { - if (tagName.equals("filter")) { - //Log.i(TAG, "Starting to parse filter..."); - readFromXml(parser); - //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth=" - // + parser.getDepth() + " tag=" + parser.getName()); - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - return true; - } - } - - static class GrantedPermissions { - int pkgFlags; - - HashSet grantedPermissions = new HashSet(); - int[] gids; - - GrantedPermissions(int pkgFlags) { - setFlags(pkgFlags); - } - - GrantedPermissions(GrantedPermissions base) { - pkgFlags = base.pkgFlags; - grantedPermissions = (HashSet) base.grantedPermissions.clone(); - - if (base.gids != null) { - gids = base.gids.clone(); - } - } - - void setFlags(int pkgFlags) { - this.pkgFlags = pkgFlags & ( - ApplicationInfo.FLAG_SYSTEM | - ApplicationInfo.FLAG_FORWARD_LOCK | - ApplicationInfo.FLAG_EXTERNAL_STORAGE); - } - } - - /** - * Settings base class for pending and resolved classes. - */ - static class PackageSettingBase extends GrantedPermissions { - final String name; - final String realName; - File codePath; - String codePathString; - File resourcePath; - String resourcePathString; - String nativeLibraryPathString; - long timeStamp; - long firstInstallTime; - long lastUpdateTime; - int versionCode; - - boolean uidError; - - PackageSignatures signatures = new PackageSignatures(); - - boolean permissionsFixed; - boolean haveGids; - - // Whether this package is currently stopped, thus can not be - // started until explicitly launched by the user. - public boolean stopped; - - // Set to true if we have never launched this app. - public boolean notLaunched; - - /* Explicitly disabled components */ - HashSet disabledComponents = new HashSet(0); - /* Explicitly enabled components */ - HashSet enabledComponents = new HashSet(0); - int enabled = COMPONENT_ENABLED_STATE_DEFAULT; - int installStatus = PKG_INSTALL_COMPLETE; - - PackageSettingBase origPackage; - - /* package name of the app that installed this package */ - String installerPackageName; - - PackageSettingBase(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int pVersionCode, int pkgFlags) { - super(pkgFlags); - this.name = name; - this.realName = realName; - init(codePath, resourcePath, nativeLibraryPathString, pVersionCode); - } - - /** - * New instance of PackageSetting with one-level-deep cloning. - */ - PackageSettingBase(PackageSettingBase base) { - super(base); - - name = base.name; - realName = base.realName; - codePath = base.codePath; - codePathString = base.codePathString; - resourcePath = base.resourcePath; - resourcePathString = base.resourcePathString; - nativeLibraryPathString = base.nativeLibraryPathString; - timeStamp = base.timeStamp; - firstInstallTime = base.firstInstallTime; - lastUpdateTime = base.lastUpdateTime; - versionCode = base.versionCode; - - uidError = base.uidError; - - signatures = new PackageSignatures(base.signatures); - - permissionsFixed = base.permissionsFixed; - haveGids = base.haveGids; - stopped = base.stopped; - notLaunched = base.notLaunched; - - disabledComponents = (HashSet) base.disabledComponents.clone(); - - enabledComponents = (HashSet) base.enabledComponents.clone(); - - enabled = base.enabled; - installStatus = base.installStatus; - - origPackage = base.origPackage; - - installerPackageName = base.installerPackageName; - } - - void init(File codePath, File resourcePath, String nativeLibraryPathString, - int pVersionCode) { - this.codePath = codePath; - this.codePathString = codePath.toString(); - this.resourcePath = resourcePath; - this.resourcePathString = resourcePath.toString(); - this.nativeLibraryPathString = nativeLibraryPathString; - this.versionCode = pVersionCode; - } - - public void setInstallerPackageName(String packageName) { - installerPackageName = packageName; - } - - String getInstallerPackageName() { - return installerPackageName; - } - - public void setInstallStatus(int newStatus) { - installStatus = newStatus; - } - - public int getInstallStatus() { - return installStatus; - } - - public void setTimeStamp(long newStamp) { - timeStamp = newStamp; - } - - /** - * Make a shallow copy of this package settings. - */ - public void copyFrom(PackageSettingBase base) { - grantedPermissions = base.grantedPermissions; - gids = base.gids; - - timeStamp = base.timeStamp; - firstInstallTime = base.firstInstallTime; - lastUpdateTime = base.lastUpdateTime; - signatures = base.signatures; - permissionsFixed = base.permissionsFixed; - haveGids = base.haveGids; - stopped = base.stopped; - notLaunched = base.notLaunched; - disabledComponents = base.disabledComponents; - enabledComponents = base.enabledComponents; - enabled = base.enabled; - installStatus = base.installStatus; - } - - boolean enableComponentLP(String componentClassName) { - boolean changed = disabledComponents.remove(componentClassName); - changed |= enabledComponents.add(componentClassName); - return changed; - } - - boolean disableComponentLP(String componentClassName) { - boolean changed = enabledComponents.remove(componentClassName); - changed |= disabledComponents.add(componentClassName); - return changed; - } - - boolean restoreComponentLP(String componentClassName) { - boolean changed = enabledComponents.remove(componentClassName); - changed |= disabledComponents.remove(componentClassName); - return changed; - } - - int currentEnabledStateLP(String componentName) { - if (enabledComponents.contains(componentName)) { - return COMPONENT_ENABLED_STATE_ENABLED; - } else if (disabledComponents.contains(componentName)) { - return COMPONENT_ENABLED_STATE_DISABLED; - } else { - return COMPONENT_ENABLED_STATE_DEFAULT; - } - } - } - - /** - * Settings data for a particular package we know about. - */ - static final class PackageSetting extends PackageSettingBase { - int userId; - PackageParser.Package pkg; - SharedUserSetting sharedUser; - - PackageSetting(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int pVersionCode, int pkgFlags) { - super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode, - pkgFlags); - } - - /** - * New instance of PackageSetting replicating the original settings. - * Note that it keeps the same PackageParser.Package instance. - */ - PackageSetting(PackageSetting orig) { - super(orig); - - userId = orig.userId; - pkg = orig.pkg; - sharedUser = orig.sharedUser; - } - - @Override - public String toString() { - return "PackageSetting{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "/" + userId + "}"; - } - } - - /** - * Settings data for a particular shared user ID we know about. - */ - static final class SharedUserSetting extends GrantedPermissions { - final String name; - int userId; - final HashSet packages = new HashSet(); - final PackageSignatures signatures = new PackageSignatures(); - - SharedUserSetting(String _name, int _pkgFlags) { - super(_pkgFlags); - name = _name; - } - - @Override - public String toString() { - return "SharedUserSetting{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "/" + userId + "}"; - } - } - - /** - * Holds information about dynamic settings. - */ - private static final class Settings { - private final File mSettingsFilename; - private final File mBackupSettingsFilename; - private final File mPackageListFilename; - private final File mStoppedPackagesFilename; - private final File mBackupStoppedPackagesFilename; - private final HashMap mPackages = - new HashMap(); - // List of replaced system applications - final HashMap mDisabledSysPackages = - new HashMap(); - - // These are the last platform API version we were using for - // the apps installed on internal and external storage. It is - // used to grant newer permissions one time during a system upgrade. - int mInternalSdkPlatform; - int mExternalSdkPlatform; - - // The user's preferred activities associated with particular intent - // filters. - private final IntentResolver mPreferredActivities = - new IntentResolver() { - @Override - protected String packageForFilter(PreferredActivity filter) { - return filter.mPref.mComponent.getPackageName(); - } - @Override - protected void dumpFilter(PrintWriter out, String prefix, - PreferredActivity filter) { - filter.mPref.dump(out, prefix, filter); - } - }; - private final HashMap mSharedUsers = - new HashMap(); - private final ArrayList mUserIds = new ArrayList(); - private final SparseArray mOtherUserIds = - new SparseArray(); - - // For reading/writing settings file. - private final ArrayList mPastSignatures = - new ArrayList(); - - // Mapping from permission names to info about them. - final HashMap mPermissions = - new HashMap(); - - // Mapping from permission tree names to info about them. - final HashMap mPermissionTrees = - new HashMap(); - - // Packages that have been uninstalled and still need their external - // storage data deleted. - final ArrayList mPackagesToBeCleaned = new ArrayList(); - - // Packages that have been renamed since they were first installed. - // Keys are the new names of the packages, values are the original - // names. The packages appear everwhere else under their original - // names. - final HashMap mRenamedPackages = new HashMap(); - - private final StringBuilder mReadMessages = new StringBuilder(); - - private static final class PendingPackage extends PackageSettingBase { - final int sharedId; - - PendingPackage(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) { - super(name, realName, codePath, resourcePath, nativeLibraryPathString, - pVersionCode, pkgFlags); - this.sharedId = sharedId; - } - } - private final ArrayList mPendingPackages - = new ArrayList(); - - Settings() { - File dataDir = Environment.getDataDirectory(); - File systemDir = new File(dataDir, "system"); - // TODO(oam): This secure dir creation needs to be moved somewhere else (later) - File systemSecureDir = new File(dataDir, "secure/system"); - systemDir.mkdirs(); - systemSecureDir.mkdirs(); - FileUtils.setPermissions(systemDir.toString(), - FileUtils.S_IRWXU|FileUtils.S_IRWXG - |FileUtils.S_IROTH|FileUtils.S_IXOTH, - -1, -1); - FileUtils.setPermissions(systemSecureDir.toString(), - FileUtils.S_IRWXU|FileUtils.S_IRWXG - |FileUtils.S_IROTH|FileUtils.S_IXOTH, - -1, -1); - mSettingsFilename = new File(systemDir, "packages.xml"); - mBackupSettingsFilename = new File(systemDir, "packages-backup.xml"); - mPackageListFilename = new File(systemDir, "packages.list"); - mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml"); - mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml"); - } - - PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage, - String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, - String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) { - final String name = pkg.packageName; - PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath, - resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add); - return p; - } - - PackageSetting peekPackageLP(String name) { - return mPackages.get(name); - /* - PackageSetting p = mPackages.get(name); - if (p != null && p.codePath.getPath().equals(codePath)) { - return p; - } - return null; - */ - } - - void setInstallStatus(String pkgName, int status) { - PackageSetting p = mPackages.get(pkgName); - if(p != null) { - if(p.getInstallStatus() != status) { - p.setInstallStatus(status); - } - } - } - - void setInstallerPackageName(String pkgName, - String installerPkgName) { - PackageSetting p = mPackages.get(pkgName); - if(p != null) { - p.setInstallerPackageName(installerPkgName); - } - } - - SharedUserSetting getSharedUserLP(String name, - int pkgFlags, boolean create) { - SharedUserSetting s = mSharedUsers.get(name); - if (s == null) { - if (!create) { - return null; - } - s = new SharedUserSetting(name, pkgFlags); - if (MULTIPLE_APPLICATION_UIDS) { - s.userId = newUserIdLP(s); - } else { - s.userId = FIRST_APPLICATION_UID; - } - Log.i(TAG, "New shared user " + name + ": id=" + s.userId); - // < 0 means we couldn't assign a userid; fall out and return - // s, which is currently null - if (s.userId >= 0) { - mSharedUsers.put(name, s); - } - } - - return s; - } - - boolean disableSystemPackageLP(String name) { - PackageSetting p = mPackages.get(name); - if(p == null) { - Log.w(TAG, "Package:"+name+" is not an installed package"); - return false; - } - PackageSetting dp = mDisabledSysPackages.get(name); - // always make sure the system package code and resource paths dont change - if (dp == null) { - if((p.pkg != null) && (p.pkg.applicationInfo != null)) { - p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; - } - mDisabledSysPackages.put(name, p); - - // a little trick... when we install the new package, we don't - // want to modify the existing PackageSetting for the built-in - // version. so at this point we need a new PackageSetting that - // is okay to muck with. - PackageSetting newp = new PackageSetting(p); - replacePackageLP(name, newp); - return true; - } - return false; - } - - PackageSetting enableSystemPackageLP(String name) { - PackageSetting p = mDisabledSysPackages.get(name); - if(p == null) { - Log.w(TAG, "Package:"+name+" is not disabled"); - return null; - } - // Reset flag in ApplicationInfo object - if((p.pkg != null) && (p.pkg.applicationInfo != null)) { - p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; - } - PackageSetting ret = addPackageLP(name, p.realName, p.codePath, p.resourcePath, - p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags); - mDisabledSysPackages.remove(name); - return ret; - } - - PackageSetting addPackageLP(String name, String realName, File codePath, File resourcePath, - String nativeLibraryPathString, int uid, int vc, int pkgFlags) { - PackageSetting p = mPackages.get(name); - if (p != null) { - if (p.userId == uid) { - return p; - } - reportSettingsProblem(Log.ERROR, - "Adding duplicate package, keeping first: " + name); - return null; - } - p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, - vc, pkgFlags); - p.userId = uid; - if (addUserIdLP(uid, p, name)) { - mPackages.put(name, p); - return p; - } - return null; - } - - SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) { - SharedUserSetting s = mSharedUsers.get(name); - if (s != null) { - if (s.userId == uid) { - return s; - } - reportSettingsProblem(Log.ERROR, - "Adding duplicate shared user, keeping first: " + name); - return null; - } - s = new SharedUserSetting(name, pkgFlags); - s.userId = uid; - if (addUserIdLP(uid, s, name)) { - mSharedUsers.put(name, s); - return s; - } - return null; - } - - // Transfer ownership of permissions from one package to another. - private void transferPermissions(String origPkg, String newPkg) { - // Transfer ownership of permissions to the new package. - for (int i=0; i<2; i++) { - HashMap permissions = - i == 0 ? mPermissionTrees : mPermissions; - for (BasePermission bp : permissions.values()) { - if (origPkg.equals(bp.sourcePackage)) { - if (DEBUG_UPGRADE) Log.v(TAG, - "Moving permission " + bp.name - + " from pkg " + bp.sourcePackage - + " to " + newPkg); - bp.sourcePackage = newPkg; - bp.packageSetting = null; - bp.perm = null; - if (bp.pendingInfo != null) { - bp.pendingInfo.packageName = newPkg; - } - bp.uid = 0; - bp.gids = null; - } - } - } - } - - private PackageSetting getPackageLP(String name, PackageSetting origPackage, - String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, - String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) { - PackageSetting p = mPackages.get(name); - if (p != null) { - if (!p.codePath.equals(codePath)) { - // Check to see if its a disabled system app - if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { - // This is an updated system app with versions in both system - // and data partition. Just let the most recent version - // take precedence. - Slog.w(TAG, "Trying to update system app code path from " + - p.codePathString + " to " + codePath.toString()); - } else { - // Just a change in the code path is not an issue, but - // let's log a message about it. - Slog.i(TAG, "Package " + name + " codePath changed from " + p.codePath - + " to " + codePath + "; Retaining data and using new"); - /* - * Since we've changed paths, we need to prefer the new - * native library path over the one stored in the - * package settings since we might have moved from - * internal to external storage or vice versa. - */ - p.nativeLibraryPathString = nativeLibraryPathString; - } - } - if (p.sharedUser != sharedUser) { - reportSettingsProblem(Log.WARN, - "Package " + name + " shared user changed from " - + (p.sharedUser != null ? p.sharedUser.name : "") - + " to " - + (sharedUser != null ? sharedUser.name : "") - + "; replacing with new"); - p = null; - } else { - if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) { - // If what we are scanning is a system package, then - // make it so, regardless of whether it was previously - // installed only in the data partition. - p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM; - } - } - } - if (p == null) { - // Create a new PackageSettings entry. this can end up here because - // of code path mismatch or user id mismatch of an updated system partition - if (!create) { - return null; - } - if (origPackage != null) { - // We are consuming the data from an existing package. - p = new PackageSetting(origPackage.name, name, codePath, resourcePath, - nativeLibraryPathString, vc, pkgFlags); - if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name - + " is adopting original package " + origPackage.name); - // Note that we will retain the new package's signature so - // that we can keep its data. - PackageSignatures s = p.signatures; - p.copyFrom(origPackage); - p.signatures = s; - p.sharedUser = origPackage.sharedUser; - p.userId = origPackage.userId; - p.origPackage = origPackage; - mRenamedPackages.put(name, origPackage.name); - name = origPackage.name; - // Update new package state. - p.setTimeStamp(codePath.lastModified()); - } else { - p = new PackageSetting(name, realName, codePath, resourcePath, - nativeLibraryPathString, vc, pkgFlags); - p.setTimeStamp(codePath.lastModified()); - p.sharedUser = sharedUser; - // If this is not a system app, it starts out stopped. - if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { - if (DEBUG_STOPPED) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Slog.i(TAG, "Stopping package " + name, e); - } - p.stopped = true; - p.notLaunched = true; - } - if (sharedUser != null) { - p.userId = sharedUser.userId; - } else if (MULTIPLE_APPLICATION_UIDS) { - // Clone the setting here for disabled system packages - PackageSetting dis = mDisabledSysPackages.get(name); - if (dis != null) { - // For disabled packages a new setting is created - // from the existing user id. This still has to be - // added to list of user id's - // Copy signatures from previous setting - if (dis.signatures.mSignatures != null) { - p.signatures.mSignatures = dis.signatures.mSignatures.clone(); - } - p.userId = dis.userId; - // Clone permissions - p.grantedPermissions = new HashSet(dis.grantedPermissions); - // Clone component info - p.disabledComponents = new HashSet(dis.disabledComponents); - p.enabledComponents = new HashSet(dis.enabledComponents); - // Add new setting to list of user ids - addUserIdLP(p.userId, p, name); - } else { - // Assign new user id - p.userId = newUserIdLP(p); - } - } else { - p.userId = FIRST_APPLICATION_UID; - } - } - if (p.userId < 0) { - reportSettingsProblem(Log.WARN, - "Package " + name + " could not be assigned a valid uid"); - return null; - } - if (add) { - // Finish adding new package by adding it and updating shared - // user preferences - addPackageSettingLP(p, name, sharedUser); - } - } - return p; - } - - private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) { - p.pkg = pkg; - pkg.mSetEnabled = p.enabled; - pkg.mSetStopped = p.stopped; - final String codePath = pkg.applicationInfo.sourceDir; - final String resourcePath = pkg.applicationInfo.publicSourceDir; - // Update code path if needed - if (!codePath.equalsIgnoreCase(p.codePathString)) { - Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName + - " changing from " + p.codePathString + " to " + codePath); - p.codePath = new File(codePath); - p.codePathString = codePath; - } - //Update resource path if needed - if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) { - Slog.w(TAG, "Resource path for pkg : " + p.pkg.packageName + - " changing from " + p.resourcePathString + " to " + resourcePath); - p.resourcePath = new File(resourcePath); - p.resourcePathString = resourcePath; - } - // Update the native library path if needed - final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir; - if (nativeLibraryPath != null - && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) { - p.nativeLibraryPathString = nativeLibraryPath; - } - // Update version code if needed - if (pkg.mVersionCode != p.versionCode) { - p.versionCode = pkg.mVersionCode; - } - // Update signatures if needed. - if (p.signatures.mSignatures == null) { - p.signatures.assignSignatures(pkg.mSignatures); - } - // If this app defines a shared user id initialize - // the shared user signatures as well. - if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) { - p.sharedUser.signatures.assignSignatures(pkg.mSignatures); - } - addPackageSettingLP(p, pkg.packageName, p.sharedUser); - } - - // Utility method that adds a PackageSetting to mPackages and - // completes updating the shared user attributes - private void addPackageSettingLP(PackageSetting p, String name, - SharedUserSetting sharedUser) { - mPackages.put(name, p); - if (sharedUser != null) { - if (p.sharedUser != null && p.sharedUser != sharedUser) { - reportSettingsProblem(Log.ERROR, - "Package " + p.name + " was user " - + p.sharedUser + " but is now " + sharedUser - + "; I am not changing its files so it will probably fail!"); - p.sharedUser.packages.remove(p); - } else if (p.userId != sharedUser.userId) { - reportSettingsProblem(Log.ERROR, - "Package " + p.name + " was user id " + p.userId - + " but is now user " + sharedUser - + " with id " + sharedUser.userId - + "; I am not changing its files so it will probably fail!"); - } - - sharedUser.packages.add(p); - p.sharedUser = sharedUser; - p.userId = sharedUser.userId; - } - } - - /* - * Update the shared user setting when a package using - * specifying the shared user id is removed. The gids - * associated with each permission of the deleted package - * are removed from the shared user's gid list only if its - * not in use by other permissions of packages in the - * shared user setting. - */ - private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) { - if ( (deletedPs == null) || (deletedPs.pkg == null)) { - Slog.i(TAG, "Trying to update info for null package. Just ignoring"); - return; - } - // No sharedUserId - if (deletedPs.sharedUser == null) { - return; - } - SharedUserSetting sus = deletedPs.sharedUser; - // Update permissions - for (String eachPerm: deletedPs.pkg.requestedPermissions) { - boolean used = false; - if (!sus.grantedPermissions.contains (eachPerm)) { - continue; - } - for (PackageSetting pkg:sus.packages) { - if (pkg.pkg != null && - !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) && - pkg.pkg.requestedPermissions.contains(eachPerm)) { - used = true; - break; - } - } - if (!used) { - // can safely delete this permission from list - sus.grantedPermissions.remove(eachPerm); - } - } - // Update gids - int newGids[] = globalGids; - for (String eachPerm : sus.grantedPermissions) { - BasePermission bp = mPermissions.get(eachPerm); - if (bp != null) { - newGids = appendInts(newGids, bp.gids); - } - } - sus.gids = newGids; - } - - private int removePackageLP(String name) { - PackageSetting p = mPackages.get(name); - if (p != null) { - mPackages.remove(name); - if (p.sharedUser != null) { - p.sharedUser.packages.remove(p); - if (p.sharedUser.packages.size() == 0) { - mSharedUsers.remove(p.sharedUser.name); - removeUserIdLP(p.sharedUser.userId); - return p.sharedUser.userId; - } - } else { - removeUserIdLP(p.userId); - return p.userId; - } - } - return -1; - } - - private void replacePackageLP(String name, PackageSetting newp) { - PackageSetting p = mPackages.get(name); - if (p != null) { - if (p.sharedUser != null) { - p.sharedUser.packages.remove(p); - p.sharedUser.packages.add(newp); - } else { - replaceUserIdLP(p.userId, newp); - } - } - mPackages.put(name, newp); - } - - private boolean addUserIdLP(int uid, Object obj, Object name) { - if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) { - return false; - } - - if (uid >= FIRST_APPLICATION_UID) { - int N = mUserIds.size(); - final int index = uid - FIRST_APPLICATION_UID; - while (index >= N) { - mUserIds.add(null); - N++; - } - if (mUserIds.get(index) != null) { - reportSettingsProblem(Log.ERROR, - "Adding duplicate user id: " + uid - + " name=" + name); - return false; - } - mUserIds.set(index, obj); - } else { - if (mOtherUserIds.get(uid) != null) { - reportSettingsProblem(Log.ERROR, - "Adding duplicate shared id: " + uid - + " name=" + name); - return false; - } - mOtherUserIds.put(uid, obj); - } - return true; - } - - public Object getUserIdLP(int uid) { - if (uid >= FIRST_APPLICATION_UID) { - final int N = mUserIds.size(); - final int index = uid - FIRST_APPLICATION_UID; - return index < N ? mUserIds.get(index) : null; - } else { - return mOtherUserIds.get(uid); - } - } - - private void removeUserIdLP(int uid) { - if (uid >= FIRST_APPLICATION_UID) { - final int N = mUserIds.size(); - final int index = uid - FIRST_APPLICATION_UID; - if (index < N) mUserIds.set(index, null); - } else { - mOtherUserIds.remove(uid); - } - } - - private void replaceUserIdLP(int uid, Object obj) { - if (uid >= FIRST_APPLICATION_UID) { - final int N = mUserIds.size(); - final int index = uid - FIRST_APPLICATION_UID; - if (index < N) mUserIds.set(index, obj); - } else { - mOtherUserIds.put(uid, obj); - } - } - - void writeStoppedLP() { - // Keep the old stopped packages around until we know the new ones have - // been successfully written. - if (mStoppedPackagesFilename.exists()) { - // Presence of backup settings file indicates that we failed - // to persist packages earlier. So preserve the older - // backup for future reference since the current packages - // might have been corrupted. - if (!mBackupStoppedPackagesFilename.exists()) { - if (!mStoppedPackagesFilename.renameTo(mBackupStoppedPackagesFilename)) { - Log.wtf(TAG, "Unable to backup package manager stopped packages, " - + "current changes will be lost at reboot"); - return; - } - } else { - mStoppedPackagesFilename.delete(); - Slog.w(TAG, "Preserving older stopped packages backup"); - } - } - - try { - FileOutputStream fstr = new FileOutputStream(mStoppedPackagesFilename); - BufferedOutputStream str = new BufferedOutputStream(fstr); - - //XmlSerializer serializer = XmlUtils.serializerInstance(); - XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(str, "utf-8"); - serializer.startDocument(null, true); - serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); - - serializer.startTag(null, "stopped-packages"); - - for (PackageSetting pkg : mPackages.values()) { - if (pkg.stopped) { - serializer.startTag(null, "pkg"); - serializer.attribute(null, "name", pkg.name); - if (pkg.notLaunched) { - serializer.attribute(null, "nl", "1"); - } - serializer.endTag(null, "pkg"); - } - } - - serializer.endTag(null, "stopped-packages"); - - serializer.endDocument(); - - str.flush(); - FileUtils.sync(fstr); - str.close(); - - // New settings successfully written, old ones are no longer - // needed. - mBackupStoppedPackagesFilename.delete(); - FileUtils.setPermissions(mStoppedPackagesFilename.toString(), - FileUtils.S_IRUSR|FileUtils.S_IWUSR - |FileUtils.S_IRGRP|FileUtils.S_IWGRP - |FileUtils.S_IROTH, - -1, -1); - - // Done, all is good! - return; - - } catch(java.io.IOException e) { - Log.wtf(TAG, "Unable to write package manager stopped packages, " - + " current changes will be lost at reboot", e); - } - - // Clean up partially written files - if (mStoppedPackagesFilename.exists()) { - if (!mStoppedPackagesFilename.delete()) { - Log.i(TAG, "Failed to clean up mangled file: " + mStoppedPackagesFilename); - } - } - } - - // Note: assumed "stopped" field is already cleared in all packages. - void readStoppedLP() { - FileInputStream str = null; - if (mBackupStoppedPackagesFilename.exists()) { - try { - str = new FileInputStream(mBackupStoppedPackagesFilename); - mReadMessages.append("Reading from backup stopped packages file\n"); - reportSettingsProblem(Log.INFO, "Need to read from backup stopped packages file"); - if (mSettingsFilename.exists()) { - // If both the backup and normal file exist, we - // ignore the normal one since it might have been - // corrupted. - Slog.w(TAG, "Cleaning up stopped packages file " - + mStoppedPackagesFilename); - mStoppedPackagesFilename.delete(); - } - } catch (java.io.IOException e) { - // We'll try for the normal settings file. - } - } - - try { - if (str == null) { - if (!mStoppedPackagesFilename.exists()) { - mReadMessages.append("No stopped packages file found\n"); - reportSettingsProblem(Log.INFO, "No stopped packages file file; " - + "assuming all started"); - // At first boot, make sure no packages are stopped. - // We usually want to have third party apps initialize - // in the stopped state, but not at first boot. - for (PackageSetting pkg : mPackages.values()) { - pkg.stopped = false; - pkg.notLaunched = false; - } - return; - } - str = new FileInputStream(mStoppedPackagesFilename); - } - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(str, null); - - int type; - while ((type=parser.next()) != XmlPullParser.START_TAG - && type != XmlPullParser.END_DOCUMENT) { - ; - } - - if (type != XmlPullParser.START_TAG) { - mReadMessages.append("No start tag found in stopped packages file\n"); - reportSettingsProblem(Log.WARN, - "No start tag found in package manager stopped packages"); - return; - } - - int outerDepth = parser.getDepth(); - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("pkg")) { - String name = parser.getAttributeValue(null, "name"); - PackageSetting ps = mPackages.get(name); - if (ps != null) { - ps.stopped = true; - if ("1".equals(parser.getAttributeValue(null, "nl"))) { - ps.notLaunched = true; - } - } else { - Slog.w(TAG, "No package known for stopped package: " + name); - } - XmlUtils.skipCurrentTag(parser); - } else { - Slog.w(TAG, "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - - str.close(); - - } catch(XmlPullParserException e) { - mReadMessages.append("Error reading: " + e.toString()); - reportSettingsProblem(Log.ERROR, "Error reading stopped packages: " + e); - Log.wtf(TAG, "Error reading package manager stopped packages", e); - - } catch(java.io.IOException e) { - mReadMessages.append("Error reading: " + e.toString()); - reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); - Log.wtf(TAG, "Error reading package manager stopped packages", e); - - } - } - - void writeLP() { - //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024); - - // Keep the old settings around until we know the new ones have - // been successfully written. - if (mSettingsFilename.exists()) { - // Presence of backup settings file indicates that we failed - // to persist settings earlier. So preserve the older - // backup for future reference since the current settings - // might have been corrupted. - if (!mBackupSettingsFilename.exists()) { - if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) { - Log.wtf(TAG, "Unable to backup package manager settings, " - + " current changes will be lost at reboot"); - return; - } - } else { - mSettingsFilename.delete(); - Slog.w(TAG, "Preserving older settings backup"); - } - } - - mPastSignatures.clear(); - - try { - FileOutputStream fstr = new FileOutputStream(mSettingsFilename); - BufferedOutputStream str = new BufferedOutputStream(fstr); - - //XmlSerializer serializer = XmlUtils.serializerInstance(); - XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(str, "utf-8"); - serializer.startDocument(null, true); - serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); - - serializer.startTag(null, "packages"); - - serializer.startTag(null, "last-platform-version"); - serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform)); - serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform)); - serializer.endTag(null, "last-platform-version"); - - serializer.startTag(null, "permission-trees"); - for (BasePermission bp : mPermissionTrees.values()) { - writePermission(serializer, bp); - } - serializer.endTag(null, "permission-trees"); - - serializer.startTag(null, "permissions"); - for (BasePermission bp : mPermissions.values()) { - writePermission(serializer, bp); - } - serializer.endTag(null, "permissions"); - - for (PackageSetting pkg : mPackages.values()) { - writePackage(serializer, pkg); - } - - for (PackageSetting pkg : mDisabledSysPackages.values()) { - writeDisabledSysPackage(serializer, pkg); - } - - serializer.startTag(null, "preferred-activities"); - for (PreferredActivity pa : mPreferredActivities.filterSet()) { - serializer.startTag(null, "item"); - pa.writeToXml(serializer); - serializer.endTag(null, "item"); - } - serializer.endTag(null, "preferred-activities"); - - for (SharedUserSetting usr : mSharedUsers.values()) { - serializer.startTag(null, "shared-user"); - serializer.attribute(null, "name", usr.name); - serializer.attribute(null, "userId", - Integer.toString(usr.userId)); - usr.signatures.writeXml(serializer, "sigs", mPastSignatures); - serializer.startTag(null, "perms"); - for (String name : usr.grantedPermissions) { - serializer.startTag(null, "item"); - serializer.attribute(null, "name", name); - serializer.endTag(null, "item"); - } - serializer.endTag(null, "perms"); - serializer.endTag(null, "shared-user"); - } - - if (mPackagesToBeCleaned.size() > 0) { - for (int i=0; i 0) { - for (HashMap.Entry e : mRenamedPackages.entrySet()) { - serializer.startTag(null, "renamed-package"); - serializer.attribute(null, "new", e.getKey()); - serializer.attribute(null, "old", e.getValue()); - serializer.endTag(null, "renamed-package"); - } - } - - serializer.endTag(null, "packages"); - - serializer.endDocument(); - - str.flush(); - FileUtils.sync(fstr); - str.close(); - - // New settings successfully written, old ones are no longer - // needed. - mBackupSettingsFilename.delete(); - FileUtils.setPermissions(mSettingsFilename.toString(), - FileUtils.S_IRUSR|FileUtils.S_IWUSR - |FileUtils.S_IRGRP|FileUtils.S_IWGRP - |FileUtils.S_IROTH, - -1, -1); - - // Write package list file now, use a JournaledFile. - // - File tempFile = new File(mPackageListFilename.toString() + ".tmp"); - JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile); - - fstr = new FileOutputStream(journal.chooseForWrite()); - str = new BufferedOutputStream(fstr); - try { - StringBuilder sb = new StringBuilder(); - for (PackageSetting pkg : mPackages.values()) { - ApplicationInfo ai = pkg.pkg.applicationInfo; - String dataPath = ai.dataDir; - boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - - // Avoid any application that has a space in its path - // or that is handled by the system. - if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID) - continue; - - // we store on each line the following information for now: - // - // pkgName - package name - // userId - application-specific user id - // debugFlag - 0 or 1 if the package is debuggable. - // dataPath - path to package's data path - // - // NOTE: We prefer not to expose all ApplicationInfo flags for now. - // - // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS - // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES: - // system/core/run-as/run-as.c - // - sb.setLength(0); - sb.append(ai.packageName); - sb.append(" "); - sb.append((int)ai.uid); - sb.append(isDebug ? " 1 " : " 0 "); - sb.append(dataPath); - sb.append("\n"); - str.write(sb.toString().getBytes()); - } - str.flush(); - FileUtils.sync(fstr); - str.close(); - journal.commit(); - } - catch (Exception e) { - journal.rollback(); - } - - FileUtils.setPermissions(mPackageListFilename.toString(), - FileUtils.S_IRUSR|FileUtils.S_IWUSR - |FileUtils.S_IRGRP|FileUtils.S_IWGRP - |FileUtils.S_IROTH, - -1, -1); - - writeStoppedLP(); - - return; - - } catch(XmlPullParserException e) { - Log.wtf(TAG, "Unable to write package manager settings, " - + "current changes will be lost at reboot", e); - } catch(java.io.IOException e) { - Log.wtf(TAG, "Unable to write package manager settings, " - + "current changes will be lost at reboot", e); - } - // Clean up partially written files - if (mSettingsFilename.exists()) { - if (!mSettingsFilename.delete()) { - Log.wtf(TAG, "Failed to clean up mangled file: " + mSettingsFilename); - } - } - //Debug.stopMethodTracing(); - } - - void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg) - throws java.io.IOException { - serializer.startTag(null, "updated-package"); - serializer.attribute(null, "name", pkg.name); - if (pkg.realName != null) { - serializer.attribute(null, "realName", pkg.realName); - } - serializer.attribute(null, "codePath", pkg.codePathString); - serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); - serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); - serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); - serializer.attribute(null, "version", String.valueOf(pkg.versionCode)); - if (!pkg.resourcePathString.equals(pkg.codePathString)) { - serializer.attribute(null, "resourcePath", pkg.resourcePathString); - } - if (pkg.nativeLibraryPathString != null) { - serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); - } - if (pkg.sharedUser == null) { - serializer.attribute(null, "userId", - Integer.toString(pkg.userId)); - } else { - serializer.attribute(null, "sharedUserId", - Integer.toString(pkg.userId)); - } - serializer.startTag(null, "perms"); - if (pkg.sharedUser == null) { - // If this is a shared user, the permissions will - // be written there. We still need to write an - // empty permissions list so permissionsFixed will - // be set. - for (final String name : pkg.grantedPermissions) { - BasePermission bp = mPermissions.get(name); - if (bp != null) { - // We only need to write signature or system permissions but this wont - // match the semantics of grantedPermissions. So write all permissions. - serializer.startTag(null, "item"); - serializer.attribute(null, "name", name); - serializer.endTag(null, "item"); - } - } - } - serializer.endTag(null, "perms"); - serializer.endTag(null, "updated-package"); - } - - void writePackage(XmlSerializer serializer, final PackageSetting pkg) - throws java.io.IOException { - serializer.startTag(null, "package"); - serializer.attribute(null, "name", pkg.name); - if (pkg.realName != null) { - serializer.attribute(null, "realName", pkg.realName); - } - serializer.attribute(null, "codePath", pkg.codePathString); - if (!pkg.resourcePathString.equals(pkg.codePathString)) { - serializer.attribute(null, "resourcePath", pkg.resourcePathString); - } - if (pkg.nativeLibraryPathString != null) { - serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); - } - serializer.attribute(null, "flags", - Integer.toString(pkg.pkgFlags)); - serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); - serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); - serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); - serializer.attribute(null, "version", String.valueOf(pkg.versionCode)); - if (pkg.sharedUser == null) { - serializer.attribute(null, "userId", - Integer.toString(pkg.userId)); - } else { - serializer.attribute(null, "sharedUserId", - Integer.toString(pkg.userId)); - } - if (pkg.uidError) { - serializer.attribute(null, "uidError", "true"); - } - if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) { - serializer.attribute(null, "enabled", - pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED - ? "true" : "false"); - } - if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) { - serializer.attribute(null, "installStatus", "false"); - } - if (pkg.installerPackageName != null) { - serializer.attribute(null, "installer", pkg.installerPackageName); - } - pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); - if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { - serializer.startTag(null, "perms"); - if (pkg.sharedUser == null) { - // If this is a shared user, the permissions will - // be written there. We still need to write an - // empty permissions list so permissionsFixed will - // be set. - for (final String name : pkg.grantedPermissions) { - serializer.startTag(null, "item"); - serializer.attribute(null, "name", name); - serializer.endTag(null, "item"); - } - } - serializer.endTag(null, "perms"); - } - if (pkg.disabledComponents.size() > 0) { - serializer.startTag(null, "disabled-components"); - for (final String name : pkg.disabledComponents) { - serializer.startTag(null, "item"); - serializer.attribute(null, "name", name); - serializer.endTag(null, "item"); - } - serializer.endTag(null, "disabled-components"); - } - if (pkg.enabledComponents.size() > 0) { - serializer.startTag(null, "enabled-components"); - for (final String name : pkg.enabledComponents) { - serializer.startTag(null, "item"); - serializer.attribute(null, "name", name); - serializer.endTag(null, "item"); - } - serializer.endTag(null, "enabled-components"); - } - - serializer.endTag(null, "package"); - } - - void writePermission(XmlSerializer serializer, BasePermission bp) - throws XmlPullParserException, java.io.IOException { - if (bp.type != BasePermission.TYPE_BUILTIN - && bp.sourcePackage != null) { - serializer.startTag(null, "item"); - serializer.attribute(null, "name", bp.name); - serializer.attribute(null, "package", bp.sourcePackage); - if (bp.protectionLevel != - PermissionInfo.PROTECTION_NORMAL) { - serializer.attribute(null, "protection", - Integer.toString(bp.protectionLevel)); - } - if (DEBUG_SETTINGS) Log.v(TAG, - "Writing perm: name=" + bp.name + " type=" + bp.type); - if (bp.type == BasePermission.TYPE_DYNAMIC) { - PermissionInfo pi = bp.perm != null ? bp.perm.info - : bp.pendingInfo; - if (pi != null) { - serializer.attribute(null, "type", "dynamic"); - if (pi.icon != 0) { - serializer.attribute(null, "icon", - Integer.toString(pi.icon)); - } - if (pi.nonLocalizedLabel != null) { - serializer.attribute(null, "label", - pi.nonLocalizedLabel.toString()); - } - } - } - serializer.endTag(null, "item"); - } - } - - ArrayList getListOfIncompleteInstallPackages() { - HashSet kList = new HashSet(mPackages.keySet()); - Iterator its = kList.iterator(); - ArrayList ret = new ArrayList(); - while(its.hasNext()) { - String key = its.next(); - PackageSetting ps = mPackages.get(key); - if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) { - ret.add(ps); - } - } - return ret; - } - - boolean readLP() { - FileInputStream str = null; - if (mBackupSettingsFilename.exists()) { - try { - str = new FileInputStream(mBackupSettingsFilename); - mReadMessages.append("Reading from backup settings file\n"); - reportSettingsProblem(Log.INFO, "Need to read from backup settings file"); - if (mSettingsFilename.exists()) { - // If both the backup and settings file exist, we - // ignore the settings since it might have been - // corrupted. - Slog.w(TAG, "Cleaning up settings file " + mSettingsFilename); - mSettingsFilename.delete(); - } - } catch (java.io.IOException e) { - // We'll try for the normal settings file. - } - } - - mPastSignatures.clear(); - - try { - if (str == null) { - if (!mSettingsFilename.exists()) { - mReadMessages.append("No settings file found\n"); - reportSettingsProblem(Log.INFO, "No settings file; creating initial state"); - return false; - } - str = new FileInputStream(mSettingsFilename); - } - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(str, null); - - int type; - while ((type=parser.next()) != XmlPullParser.START_TAG - && type != XmlPullParser.END_DOCUMENT) { - ; - } - - if (type != XmlPullParser.START_TAG) { - mReadMessages.append("No start tag found in settings file\n"); - reportSettingsProblem(Log.WARN, "No start tag found in package manager settings"); - Log.wtf(TAG, "No start tag found in package manager settings"); - return false; - } - - int outerDepth = parser.getDepth(); - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("package")) { - readPackageLP(parser); - } else if (tagName.equals("permissions")) { - readPermissionsLP(mPermissions, parser); - } else if (tagName.equals("permission-trees")) { - readPermissionsLP(mPermissionTrees, parser); - } else if (tagName.equals("shared-user")) { - readSharedUserLP(parser); - } else if (tagName.equals("preferred-packages")) { - // no longer used. - } else if (tagName.equals("preferred-activities")) { - readPreferredActivitiesLP(parser); - } else if(tagName.equals("updated-package")) { - readDisabledSysPackageLP(parser); - } else if (tagName.equals("cleaning-package")) { - String name = parser.getAttributeValue(null, "name"); - if (name != null) { - mPackagesToBeCleaned.add(name); - } - } else if (tagName.equals("renamed-package")) { - String nname = parser.getAttributeValue(null, "new"); - String oname = parser.getAttributeValue(null, "old"); - if (nname != null && oname != null) { - mRenamedPackages.put(nname, oname); - } - } else if (tagName.equals("last-platform-version")) { - mInternalSdkPlatform = mExternalSdkPlatform = 0; - try { - String internal = parser.getAttributeValue(null, "internal"); - if (internal != null) { - mInternalSdkPlatform = Integer.parseInt(internal); - } - String external = parser.getAttributeValue(null, "external"); - if (external != null) { - mExternalSdkPlatform = Integer.parseInt(external); - } - } catch (NumberFormatException e) { - } - } else { - Slog.w(TAG, "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - - str.close(); - - } catch(XmlPullParserException e) { - mReadMessages.append("Error reading: " + e.toString()); - reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); - Log.wtf(TAG, "Error reading package manager settings", e); - - } catch(java.io.IOException e) { - mReadMessages.append("Error reading: " + e.toString()); - reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); - Log.wtf(TAG, "Error reading package manager settings", e); - - } - - final int N = mPendingPackages.size(); - for (int i=0; i out, - XmlPullParser parser) - throws IOException, XmlPullParserException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("item")) { - String name = parser.getAttributeValue(null, "name"); - String sourcePackage = parser.getAttributeValue(null, "package"); - String ptype = parser.getAttributeValue(null, "type"); - if (name != null && sourcePackage != null) { - boolean dynamic = "dynamic".equals(ptype); - BasePermission bp = new BasePermission(name, sourcePackage, - dynamic - ? BasePermission.TYPE_DYNAMIC - : BasePermission.TYPE_NORMAL); - bp.protectionLevel = readInt(parser, null, "protection", - PermissionInfo.PROTECTION_NORMAL); - if (dynamic) { - PermissionInfo pi = new PermissionInfo(); - pi.packageName = sourcePackage.intern(); - pi.name = name.intern(); - pi.icon = readInt(parser, null, "icon", 0); - pi.nonLocalizedLabel = parser.getAttributeValue( - null, "label"); - pi.protectionLevel = bp.protectionLevel; - bp.pendingInfo = pi; - } - out.put(bp.name, bp); - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: permissions has" - + " no name at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Unknown element reading permissions: " - + parser.getName() + " at " - + parser.getPositionDescription()); - } - XmlUtils.skipCurrentTag(parser); - } - } - - private void readDisabledSysPackageLP(XmlPullParser parser) - throws XmlPullParserException, IOException { - String name = parser.getAttributeValue(null, "name"); - String realName = parser.getAttributeValue(null, "realName"); - String codePathStr = parser.getAttributeValue(null, "codePath"); - String resourcePathStr = parser.getAttributeValue(null, "resourcePath"); - String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); - if (resourcePathStr == null) { - resourcePathStr = codePathStr; - } - String version = parser.getAttributeValue(null, "version"); - int versionCode = 0; - if (version != null) { - try { - versionCode = Integer.parseInt(version); - } catch (NumberFormatException e) { - } - } - - int pkgFlags = 0; - pkgFlags |= ApplicationInfo.FLAG_SYSTEM; - PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr), - new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags); - String timeStampStr = parser.getAttributeValue(null, "ft"); - if (timeStampStr != null) { - try { - long timeStamp = Long.parseLong(timeStampStr, 16); - ps.setTimeStamp(timeStamp); - } catch (NumberFormatException e) { - } - } else { - timeStampStr = parser.getAttributeValue(null, "ts"); - if (timeStampStr != null) { - try { - long timeStamp = Long.parseLong(timeStampStr); - ps.setTimeStamp(timeStamp); - } catch (NumberFormatException e) { - } - } - } - timeStampStr = parser.getAttributeValue(null, "it"); - if (timeStampStr != null) { - try { - ps.firstInstallTime = Long.parseLong(timeStampStr, 16); - } catch (NumberFormatException e) { - } - } - timeStampStr = parser.getAttributeValue(null, "ut"); - if (timeStampStr != null) { - try { - ps.lastUpdateTime = Long.parseLong(timeStampStr, 16); - } catch (NumberFormatException e) { - } - } - String idStr = parser.getAttributeValue(null, "userId"); - ps.userId = idStr != null ? Integer.parseInt(idStr) : 0; - if(ps.userId <= 0) { - String sharedIdStr = parser.getAttributeValue(null, "sharedUserId"); - ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; - } - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("perms")) { - readGrantedPermissionsLP(parser, - ps.grantedPermissions); - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - mDisabledSysPackages.put(name, ps); - } - - private void readPackageLP(XmlPullParser parser) - throws XmlPullParserException, IOException { - String name = null; - String realName = null; - String idStr = null; - String sharedIdStr = null; - String codePathStr = null; - String resourcePathStr = null; - String nativeLibraryPathStr = null; - String systemStr = null; - String installerPackageName = null; - String uidError = null; - int pkgFlags = 0; - long timeStamp = 0; - long firstInstallTime = 0; - long lastUpdateTime = 0; - PackageSettingBase packageSetting = null; - String version = null; - int versionCode = 0; - try { - name = parser.getAttributeValue(null, "name"); - realName = parser.getAttributeValue(null, "realName"); - idStr = parser.getAttributeValue(null, "userId"); - uidError = parser.getAttributeValue(null, "uidError"); - sharedIdStr = parser.getAttributeValue(null, "sharedUserId"); - codePathStr = parser.getAttributeValue(null, "codePath"); - resourcePathStr = parser.getAttributeValue(null, "resourcePath"); - nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); - version = parser.getAttributeValue(null, "version"); - if (version != null) { - try { - versionCode = Integer.parseInt(version); - } catch (NumberFormatException e) { - } - } - installerPackageName = parser.getAttributeValue(null, "installer"); - - systemStr = parser.getAttributeValue(null, "flags"); - if (systemStr != null) { - try { - pkgFlags = Integer.parseInt(systemStr); - } catch (NumberFormatException e) { - } - } else { - // For backward compatibility - systemStr = parser.getAttributeValue(null, "system"); - if (systemStr != null) { - pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0; - } else { - // Old settings that don't specify system... just treat - // them as system, good enough. - pkgFlags |= ApplicationInfo.FLAG_SYSTEM; - } - } - String timeStampStr = parser.getAttributeValue(null, "ft"); - if (timeStampStr != null) { - try { - timeStamp = Long.parseLong(timeStampStr, 16); - } catch (NumberFormatException e) { - } - } else { - timeStampStr = parser.getAttributeValue(null, "ts"); - if (timeStampStr != null) { - try { - timeStamp = Long.parseLong(timeStampStr); - } catch (NumberFormatException e) { - } - } - } - timeStampStr = parser.getAttributeValue(null, "it"); - if (timeStampStr != null) { - try { - firstInstallTime = Long.parseLong(timeStampStr, 16); - } catch (NumberFormatException e) { - } - } - timeStampStr = parser.getAttributeValue(null, "ut"); - if (timeStampStr != null) { - try { - lastUpdateTime = Long.parseLong(timeStampStr, 16); - } catch (NumberFormatException e) { - } - } - if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name - + " userId=" + idStr + " sharedUserId=" + sharedIdStr); - int userId = idStr != null ? Integer.parseInt(idStr) : 0; - if (resourcePathStr == null) { - resourcePathStr = codePathStr; - } - if (realName != null) { - realName = realName.intern(); - } - if (name == null) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has no name at " - + parser.getPositionDescription()); - } else if (codePathStr == null) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has no codePath at " - + parser.getPositionDescription()); - } else if (userId > 0) { - packageSetting = addPackageLP(name.intern(), realName, new File(codePathStr), - new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode, - pkgFlags); - if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name - + ": userId=" + userId + " pkg=" + packageSetting); - if (packageSetting == null) { - reportSettingsProblem(Log.ERROR, - "Failure adding uid " + userId - + " while parsing settings at " - + parser.getPositionDescription()); - } else { - packageSetting.setTimeStamp(timeStamp); - packageSetting.firstInstallTime = firstInstallTime; - packageSetting.lastUpdateTime = lastUpdateTime; - } - } else if (sharedIdStr != null) { - userId = sharedIdStr != null - ? Integer.parseInt(sharedIdStr) : 0; - if (userId > 0) { - packageSetting = new PendingPackage(name.intern(), realName, - new File(codePathStr), new File(resourcePathStr), - nativeLibraryPathStr, userId, versionCode, pkgFlags); - packageSetting.setTimeStamp(timeStamp); - packageSetting.firstInstallTime = firstInstallTime; - packageSetting.lastUpdateTime = lastUpdateTime; - mPendingPackages.add((PendingPackage) packageSetting); - if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name - + ": sharedUserId=" + userId + " pkg=" - + packageSetting); - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: package " - + name + " has bad sharedId " + sharedIdStr - + " at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: package " - + name + " has bad userId " + idStr + " at " - + parser.getPositionDescription()); - } - } catch (NumberFormatException e) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: package " - + name + " has bad userId " + idStr + " at " - + parser.getPositionDescription()); - } - if (packageSetting != null) { - packageSetting.uidError = "true".equals(uidError); - packageSetting.installerPackageName = installerPackageName; - packageSetting.nativeLibraryPathString = nativeLibraryPathStr; - final String enabledStr = parser.getAttributeValue(null, "enabled"); - if (enabledStr != null) { - if (enabledStr.equalsIgnoreCase("true")) { - packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED; - } else if (enabledStr.equalsIgnoreCase("false")) { - packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED; - } else if (enabledStr.equalsIgnoreCase("default")) { - packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT; - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: package " - + name + " has bad enabled value: " + idStr - + " at " + parser.getPositionDescription()); - } - } else { - packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT; - } - final String installStatusStr = parser.getAttributeValue(null, "installStatus"); - if (installStatusStr != null) { - if (installStatusStr.equalsIgnoreCase("false")) { - packageSetting.installStatus = PKG_INSTALL_INCOMPLETE; - } else { - packageSetting.installStatus = PKG_INSTALL_COMPLETE; - } - } - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("disabled-components")) { - readDisabledComponentsLP(packageSetting, parser); - } else if (tagName.equals("enabled-components")) { - readEnabledComponentsLP(packageSetting, parser); - } else if (tagName.equals("sigs")) { - packageSetting.signatures.readXml(parser, mPastSignatures); - } else if (tagName.equals("perms")) { - readGrantedPermissionsLP(parser, - packageSetting.grantedPermissions); - packageSetting.permissionsFixed = true; - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - } else { - XmlUtils.skipCurrentTag(parser); - } - } - - private void readDisabledComponentsLP(PackageSettingBase packageSetting, - XmlPullParser parser) - throws IOException, XmlPullParserException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("item")) { - String name = parser.getAttributeValue(null, "name"); - if (name != null) { - packageSetting.disabledComponents.add(name.intern()); - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has" - + " no name at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - } - XmlUtils.skipCurrentTag(parser); - } - } - - private void readEnabledComponentsLP(PackageSettingBase packageSetting, - XmlPullParser parser) - throws IOException, XmlPullParserException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("item")) { - String name = parser.getAttributeValue(null, "name"); - if (name != null) { - packageSetting.enabledComponents.add(name.intern()); - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has" - + " no name at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - } - XmlUtils.skipCurrentTag(parser); - } - } - - private void readSharedUserLP(XmlPullParser parser) - throws XmlPullParserException, IOException { - String name = null; - String idStr = null; - int pkgFlags = 0; - SharedUserSetting su = null; - try { - name = parser.getAttributeValue(null, "name"); - idStr = parser.getAttributeValue(null, "userId"); - int userId = idStr != null ? Integer.parseInt(idStr) : 0; - if ("true".equals(parser.getAttributeValue(null, "system"))) { - pkgFlags |= ApplicationInfo.FLAG_SYSTEM; - } - if (name == null) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has no name at " - + parser.getPositionDescription()); - } else if (userId == 0) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: shared-user " - + name + " has bad userId " + idStr + " at " - + parser.getPositionDescription()); - } else { - if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) { - reportSettingsProblem(Log.ERROR, - "Occurred while parsing settings at " - + parser.getPositionDescription()); - } - } - } catch (NumberFormatException e) { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: package " - + name + " has bad userId " + idStr + " at " - + parser.getPositionDescription()); - }; - - if (su != null) { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("sigs")) { - su.signatures.readXml(parser, mPastSignatures); - } else if (tagName.equals("perms")) { - readGrantedPermissionsLP(parser, su.grantedPermissions); - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - - } else { - XmlUtils.skipCurrentTag(parser); - } - } - - private void readGrantedPermissionsLP(XmlPullParser parser, - HashSet outPerms) throws IOException, XmlPullParserException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("item")) { - String name = parser.getAttributeValue(null, "name"); - if (name != null) { - outPerms.add(name.intern()); - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: has" - + " no name at " + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - } - XmlUtils.skipCurrentTag(parser); - } - } - - private void readPreferredActivitiesLP(XmlPullParser parser) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("item")) { - PreferredActivity pa = new PreferredActivity(parser); - if (pa.mPref.getParseError() == null) { - mPreferredActivities.addFilter(pa); - } else { - reportSettingsProblem(Log.WARN, - "Error in package manager settings: " - + pa.mPref.getParseError() + " at " - + parser.getPositionDescription()); - } - } else { - reportSettingsProblem(Log.WARN, - "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - } - - // Returns -1 if we could not find an available UserId to assign - private int newUserIdLP(Object obj) { - // Let's be stupidly inefficient for now... - final int N = mUserIds.size(); - for (int i=0; i= MAX_APPLICATION_UIDS) { - return -1; - } - - mUserIds.add(obj); - return FIRST_APPLICATION_UID + N; - } - - public PackageSetting getDisabledSystemPkg(String name) { - synchronized(mPackages) { - PackageSetting ps = mDisabledSysPackages.get(name); - return ps; - } - } - - boolean isEnabledLP(ComponentInfo componentInfo, int flags) { - if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - return true; - } - final PackageSetting packageSettings = mPackages.get(componentInfo.packageName); - if (DEBUG_SETTINGS) { - Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName - + " componentName = " + componentInfo.name); - Log.v(TAG, "enabledComponents: " - + Arrays.toString(packageSettings.enabledComponents.toArray())); - Log.v(TAG, "disabledComponents: " - + Arrays.toString(packageSettings.disabledComponents.toArray())); - } - if (packageSettings == null) { - return false; - } - if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED - || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled - && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) { - return false; - } - if (packageSettings.enabledComponents.contains(componentInfo.name)) { - return true; - } - if (packageSettings.disabledComponents.contains(componentInfo.name)) { - return false; - } - return componentInfo.enabled; - } - } - // ------- apps on sdcard specific code ------- static final boolean DEBUG_SD_INSTALL = false; + private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD"; + private static final String SD_ENCRYPTION_ALGORITHM = "AES"; - static final int MAX_CONTAINERS = 250; + private boolean mMediaMounted = false; private String getEncryptKey() { @@ -9956,14 +7429,13 @@ class PackageManagerService extends IPackageManager.Stub { Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae); return null; } catch (IOException ioe) { - Slog.e(TAG, "Failed to retrieve encryption keys with exception: " - + ioe); + Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe); return null; } } - /* package */ static String getTempContainerId() { + /* package */static String getTempContainerId() { int tmpIdx = 1; String list[] = PackageHelper.getSecureContainerList(); if (list != null) { @@ -9986,416 +7458,450 @@ class PackageManagerService extends IPackageManager.Stub { return mTempContainerPrefix + tmpIdx; } - /* - * Update media status on PackageManager. - */ - public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) { - int callingUid = Binder.getCallingUid(); - if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { - throw new SecurityException("Media status can only be updated by the system"); - } - synchronized (mPackages) { - Log.i(TAG, "Updating external media status from " + - (mMediaMounted ? "mounted" : "unmounted") + " to " + - (mediaStatus ? "mounted" : "unmounted")); - if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + - mediaStatus+", mMediaMounted=" + mMediaMounted); - if (mediaStatus == mMediaMounted) { - Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, - reportStatus ? 1 : 0, -1); - mHandler.sendMessage(msg); - return; - } - mMediaMounted = mediaStatus; - } - // Queue up an async operation since the package installation may take a little while. - mHandler.post(new Runnable() { - public void run() { - mHandler.removeCallbacks(this); - updateExternalMediaStatusInner(mediaStatus, reportStatus); - } - }); - } + /* + * Update media status on PackageManager. + */ + public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) { + int callingUid = Binder.getCallingUid(); + if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { + throw new SecurityException("Media status can only be updated by the system"); + } + // reader; this apparently protects mMediaMounted, but should probably + // be a different lock in that case. + synchronized (mPackages) { + Log.i(TAG, "Updating external media status from " + + (mMediaMounted ? "mounted" : "unmounted") + " to " + + (mediaStatus ? "mounted" : "unmounted")); + if (DEBUG_SD_INSTALL) + Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus + + ", mMediaMounted=" + mMediaMounted); + if (mediaStatus == mMediaMounted) { + final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 + : 0, -1); + mHandler.sendMessage(msg); + return; + } + mMediaMounted = mediaStatus; + } + // Queue up an async operation since the package installation may take a + // little while. + mHandler.post(new Runnable() { + public void run() { + // TODO fix this; this does nothing. + mHandler.removeCallbacks(this); + updateExternalMediaStatusInner(mediaStatus, reportStatus); + } + }); + } + + /* + * Collect information of applications on external media, map them against + * existing containers and update information based on current mount status. + * Please note that we always have to report status if reportStatus has been + * set to true especially when unloading packages. + */ + private void updateExternalMediaStatusInner(boolean mediaStatus, boolean reportStatus) { + // Collection of uids + int uidArr[] = null; + // Collection of stale containers + HashSet removeCids = new HashSet(); + // Collection of packages on external media with valid containers. + HashMap processCids = new HashMap(); + // Get list of secure containers. + final String list[] = PackageHelper.getSecureContainerList(); + if (list == null || list.length == 0) { + Log.i(TAG, "No secure containers on sdcard"); + } else { + // Process list of secure containers and categorize them + // as active or stale based on their package internal state. + int uidList[] = new int[list.length]; + int num = 0; + // reader + synchronized (mPackages) { + for (String cid : list) { + SdInstallArgs args = new SdInstallArgs(cid); + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Processing container " + cid); + String pkgName = args.getPackageName(); + if (pkgName == null) { + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Container : " + cid + " stale"); + removeCids.add(cid); + continue; + } + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Looking for pkg : " + pkgName); + PackageSetting ps = mSettings.mPackages.get(pkgName); + // The package status is changed only if the code path + // matches between settings and the container id. + if (ps != null && ps.codePathString != null + && ps.codePathString.equals(args.getCodePath())) { + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName + + " at code path: " + ps.codePathString); + // We do have a valid package installed on sdcard + processCids.put(args, ps.codePathString); + int uid = ps.userId; + if (uid != -1) { + uidList[num++] = uid; + } + } else { + // Stale container on sdcard. Just delete + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Container : " + cid + " stale"); + removeCids.add(cid); + } + } + } + + if (num > 0) { + // Sort uid list + Arrays.sort(uidList, 0, num); + // Throw away duplicates + uidArr = new int[num]; + uidArr[0] = uidList[0]; + int di = 0; + for (int i = 1; i < num; i++) { + if (uidList[i - 1] != uidList[i]) { + uidArr[di++] = uidList[i]; + } + } + } + } + // Process packages with valid entries. + if (mediaStatus) { + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Loading packages"); + loadMediaPackages(processCids, uidArr, removeCids); + startCleaningPackages(); + } else { + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Unloading packages"); + unloadMediaPackages(processCids, uidArr, reportStatus); + } + } + + private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList pkgList, + int uidArr[], IIntentReceiver finishedReceiver) { + int size = pkgList.size(); + if (size > 0) { + // Send broadcasts here + Bundle extras = new Bundle(); + extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList + .toArray(new String[size])); + if (uidArr != null) { + extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr); + } + String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE + : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; + sendPackageBroadcast(action, null, extras, null, finishedReceiver); + } + } /* - * Collect information of applications on external media, map them - * against existing containers and update information based on current - * mount status. Please note that we always have to report status - * if reportStatus has been set to true especially when unloading packages. - */ - private void updateExternalMediaStatusInner(boolean mediaStatus, - boolean reportStatus) { - // Collection of uids - int uidArr[] = null; - // Collection of stale containers - HashSet removeCids = new HashSet(); - // Collection of packages on external media with valid containers. - HashMap processCids = new HashMap(); - // Get list of secure containers. - final String list[] = PackageHelper.getSecureContainerList(); - if (list == null || list.length == 0) { - Log.i(TAG, "No secure containers on sdcard"); - } else { - // Process list of secure containers and categorize them - // as active or stale based on their package internal state. - int uidList[] = new int[list.length]; - int num = 0; - synchronized (mPackages) { - for (String cid : list) { - SdInstallArgs args = new SdInstallArgs(cid); - if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid); - String pkgName = args.getPackageName(); - if (pkgName == null) { - if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale"); - removeCids.add(cid); - continue; - } - if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName); - PackageSetting ps = mSettings.mPackages.get(pkgName); - // The package status is changed only if the code path - // matches between settings and the container id. - if (ps != null && ps.codePathString != null && - ps.codePathString.equals(args.getCodePath())) { - if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + - " corresponds to pkg : " + pkgName + - " at code path: " + ps.codePathString); - // We do have a valid package installed on sdcard - processCids.put(args, ps.codePathString); - int uid = ps.userId; - if (uid != -1) { - uidList[num++] = uid; - } - } else { - // Stale container on sdcard. Just delete - if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale"); - removeCids.add(cid); - } + * Look at potentially valid container ids from processCids If package + * information doesn't match the one on record or package scanning fails, + * the cid is added to list of removeCids. We currently don't delete stale + * containers. + */ + private void loadMediaPackages(HashMap processCids, int uidArr[], + HashSet removeCids) { + ArrayList pkgList = new ArrayList(); + Set keys = processCids.keySet(); + boolean doGc = false; + for (SdInstallArgs args : keys) { + String codePath = processCids.get(args); + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Loading container : " + args.cid); + int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR; + try { + // Make sure there are no container errors first. + if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) { + Slog.e(TAG, "Failed to mount cid : " + args.cid + + " when installing from sdcard"); + continue; + } + // Check code path here. + if (codePath == null || !codePath.equals(args.getCodePath())) { + Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath() + + " does not match one in settings " + codePath); + continue; + } + // Parse package + int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags; + doGc = true; + synchronized (mInstallLock) { + final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags, + 0, 0); + // Scan the package + if (pkg != null) { + /* + * TODO why is the lock being held? doPostInstall is + * called in other places without the lock. This needs + * to be straightened out. + */ + // writer + synchronized (mPackages) { + retCode = PackageManager.INSTALL_SUCCEEDED; + pkgList.add(pkg.packageName); + // Post process args + args.doPostInstall(PackageManager.INSTALL_SUCCEEDED); + } + } else { + Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard"); + } + } + + } finally { + if (retCode != PackageManager.INSTALL_SUCCEEDED) { + // Don't destroy container here. Wait till gc clears things + // up. + removeCids.add(args.cid); + } + } + } + // writer + synchronized (mPackages) { + // If the platform SDK has changed since the last time we booted, + // we need to re-grant app permission to catch any new ones that + // appear. This is really a hack, and means that apps can in some + // cases get permissions that the user didn't initially explicitly + // allow... it would be nice to have some better way to handle + // this situation. + final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion; + if (regrantPermissions) + Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to " + + mSdkVersion + "; regranting permissions for external storage"); + mSettings.mExternalSdkPlatform = mSdkVersion; + + // Make sure group IDs have been assigned, and any permission + // changes in other apps are accounted for + updatePermissionsLPw(null, null, true, regrantPermissions, regrantPermissions); + // can downgrade to reader + // Persist settings + mSettings.writeLPr(); + } + // Send a broadcast to let everyone know we are done processing + if (pkgList.size() > 0) { + sendResourcesChangedBroadcast(true, pkgList, uidArr, null); + } + // Force gc to avoid any stale parser references that we might have. + if (doGc) { + Runtime.getRuntime().gc(); + } + // List stale containers and destroy stale temporary containers. + if (removeCids != null) { + for (String cid : removeCids) { + if (cid.startsWith(mTempContainerPrefix)) { + Log.i(TAG, "Destroying stale temporary container " + cid); + PackageHelper.destroySdDir(cid); + } else { + Log.w(TAG, "Container " + cid + " is stale"); } } - - if (num > 0) { - // Sort uid list - Arrays.sort(uidList, 0, num); - // Throw away duplicates - uidArr = new int[num]; - uidArr[0] = uidList[0]; - int di = 0; - for (int i = 1; i < num; i++) { - if (uidList[i-1] != uidList[i]) { - uidArr[di++] = uidList[i]; - } - } - } - } - // Process packages with valid entries. - if (mediaStatus) { - if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); - loadMediaPackages(processCids, uidArr, removeCids); - startCleaningPackages(); - } else { - if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages"); - unloadMediaPackages(processCids, uidArr, reportStatus); - } - } - - private void sendResourcesChangedBroadcast(boolean mediaStatus, - ArrayList pkgList, int uidArr[], IIntentReceiver finishedReceiver) { - int size = pkgList.size(); - if (size > 0) { - // Send broadcasts here - Bundle extras = new Bundle(); - extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, - pkgList.toArray(new String[size])); - if (uidArr != null) { - extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr); - } - String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE - : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; - sendPackageBroadcast(action, null, extras, null, finishedReceiver); - } - } + } + } /* - * Look at potentially valid container ids from processCids - * If package information doesn't match the one on record - * or package scanning fails, the cid is added to list of - * removeCids. We currently don't delete stale containers. - */ - private void loadMediaPackages(HashMap processCids, - int uidArr[], HashSet removeCids) { - ArrayList pkgList = new ArrayList(); - Set keys = processCids.keySet(); - boolean doGc = false; - for (SdInstallArgs args : keys) { - String codePath = processCids.get(args); - if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : " - + args.cid); - int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR; - try { - // Make sure there are no container errors first. - if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) - != PackageManager.INSTALL_SUCCEEDED) { - Slog.e(TAG, "Failed to mount cid : " + args.cid + - " when installing from sdcard"); - continue; - } - // Check code path here. - if (codePath == null || !codePath.equals(args.getCodePath())) { - Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+ - " does not match one in settings " + codePath); - continue; - } - // Parse package - int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags; - doGc = true; - synchronized (mInstallLock) { - final PackageParser.Package pkg = scanPackageLI(new File(codePath), - parseFlags, 0, 0); - // Scan the package - if (pkg != null) { - synchronized (mPackages) { - retCode = PackageManager.INSTALL_SUCCEEDED; - pkgList.add(pkg.packageName); - // Post process args - args.doPostInstall(PackageManager.INSTALL_SUCCEEDED); - } - } else { - Slog.i(TAG, "Failed to install pkg from " + - codePath + " from sdcard"); - } - } - - } finally { - if (retCode != PackageManager.INSTALL_SUCCEEDED) { - // Don't destroy container here. Wait till gc clears things up. - removeCids.add(args.cid); - } - } - } - synchronized (mPackages) { - // If the platform SDK has changed since the last time we booted, - // we need to re-grant app permission to catch any new ones that - // appear. This is really a hack, and means that apps can in some - // cases get permissions that the user didn't initially explicitly - // allow... it would be nice to have some better way to handle - // this situation. - final boolean regrantPermissions = mSettings.mExternalSdkPlatform - != mSdkVersion; - if (regrantPermissions) Slog.i(TAG, "Platform changed from " - + mSettings.mExternalSdkPlatform + " to " + mSdkVersion - + "; regranting permissions for external storage"); - mSettings.mExternalSdkPlatform = mSdkVersion; - - // Make sure group IDs have been assigned, and any permission - // changes in other apps are accounted for - updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions); - // Persist settings - mSettings.writeLP(); - } - // Send a broadcast to let everyone know we are done processing - if (pkgList.size() > 0) { - sendResourcesChangedBroadcast(true, pkgList, uidArr, null); - } - // Force gc to avoid any stale parser references that we might have. - if (doGc) { - Runtime.getRuntime().gc(); - } - // List stale containers and destroy stale temporary containers. - if (removeCids != null) { - for (String cid : removeCids) { - if (cid.startsWith(mTempContainerPrefix)) { - Log.i(TAG, "Destroying stale temporary container " + cid); - PackageHelper.destroySdDir(cid); - } else { - Log.w(TAG, "Container " + cid + " is stale"); - } + * Utility method to unload a list of specified containers + */ + private void unloadAllContainers(Set cidArgs) { + // Just unmount all valid containers. + for (SdInstallArgs arg : cidArgs) { + synchronized (mInstallLock) { + arg.doPostDeleteLI(false); } } } - /* - * Utility method to unload a list of specified containers - */ - private void unloadAllContainers(Set cidArgs) { - // Just unmount all valid containers. - for (SdInstallArgs arg : cidArgs) { - synchronized (mInstallLock) { - arg.doPostDeleteLI(false); - } - } - } + /* + * Unload packages mounted on external media. This involves deleting package + * data from internal structures, sending broadcasts about diabled packages, + * gc'ing to free up references, unmounting all secure containers + * corresponding to packages on external media, and posting a + * UPDATED_MEDIA_STATUS message if status has been requested. Please note + * that we always have to post this message if status has been requested no + * matter what. + */ + private void unloadMediaPackages(HashMap processCids, int uidArr[], + final boolean reportStatus) { + if (DEBUG_SD_INSTALL) + Log.i(TAG, "unloading media packages"); + ArrayList pkgList = new ArrayList(); + ArrayList failedList = new ArrayList(); + final Set keys = processCids.keySet(); + for (SdInstallArgs args : keys) { + String pkgName = args.getPackageName(); + if (DEBUG_SD_INSTALL) + Log.i(TAG, "Trying to unload pkg : " + pkgName); + // Delete package internally + PackageRemovedInfo outInfo = new PackageRemovedInfo(); + synchronized (mInstallLock) { + boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA, + outInfo, false); + if (res) { + pkgList.add(pkgName); + } else { + Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName); + failedList.add(args); + } + } + } - /* - * Unload packages mounted on external media. This involves deleting - * package data from internal structures, sending broadcasts about - * diabled packages, gc'ing to free up references, unmounting all - * secure containers corresponding to packages on external media, and - * posting a UPDATED_MEDIA_STATUS message if status has been requested. - * Please note that we always have to post this message if status has - * been requested no matter what. - */ - private void unloadMediaPackages(HashMap processCids, - int uidArr[], final boolean reportStatus) { - if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages"); - ArrayList pkgList = new ArrayList(); - ArrayList failedList = new ArrayList(); - final Set keys = processCids.keySet(); - for (SdInstallArgs args : keys) { - String pkgName = args.getPackageName(); - if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName); - // Delete package internally - PackageRemovedInfo outInfo = new PackageRemovedInfo(); - synchronized (mInstallLock) { - boolean res = deletePackageLI(pkgName, false, - PackageManager.DONT_DELETE_DATA, outInfo, false); - if (res) { - pkgList.add(pkgName); - } else { - Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName); - failedList.add(args); - } - } - } + // reader + synchronized (mPackages) { + // We didn't update the settings after removing each package; + // write them now for all packages. + mSettings.writeLPr(); + } - synchronized (mPackages) { - // We didn't update the settings after removing each package; - // write them now for all packages. - mSettings.writeLP(); - } + // We have to absolutely send UPDATED_MEDIA_STATUS only + // after confirming that all the receivers processed the ordered + // broadcast when packages get disabled, force a gc to clean things up. + // and unload all the containers. + if (pkgList.size() > 0) { + sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() { + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean ordered, boolean sticky) throws RemoteException { + Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, + reportStatus ? 1 : 0, 1, keys); + mHandler.sendMessage(msg); + } + }); + } else { + Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1, + keys); + mHandler.sendMessage(msg); + } + } - // We have to absolutely send UPDATED_MEDIA_STATUS only - // after confirming that all the receivers processed the ordered - // broadcast when packages get disabled, force a gc to clean things up. - // and unload all the containers. - if (pkgList.size() > 0) { - sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() { - public void performReceive(Intent intent, int resultCode, String data, Bundle extras, - boolean ordered, boolean sticky) throws RemoteException { - Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, - reportStatus ? 1 : 0, 1, keys); - mHandler.sendMessage(msg); - } - }); - } else { - Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, - reportStatus ? 1 : 0, -1, keys); - mHandler.sendMessage(msg); - } - } + public void movePackage(final String packageName, final IPackageMoveObserver observer, + final int flags) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); + int returnCode = PackageManager.MOVE_SUCCEEDED; + int currFlags = 0; + int newFlags = 0; + // reader + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(packageName); + if (pkg == null) { + returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; + } else { + // Disable moving fwd locked apps and system packages + if (pkg.applicationInfo != null && isSystemApp(pkg)) { + Slog.w(TAG, "Cannot move system application"); + returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE; + } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) { + Slog.w(TAG, "Cannot move forward locked app."); + returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED; + } else if (pkg.mOperationPending) { + Slog.w(TAG, "Attempt to move package which has pending operations"); + returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING; + } else { + // Find install location first + if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 + && (flags & PackageManager.MOVE_INTERNAL) != 0) { + Slog.w(TAG, "Ambigous flags specified for move location."); + returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; + } else { + newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL + : PackageManager.INSTALL_INTERNAL; + currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL + : PackageManager.INSTALL_INTERNAL; + if (newFlags == currFlags) { + Slog.w(TAG, "No move required. Trying to move to same location"); + returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; + } + } + if (returnCode == PackageManager.MOVE_SUCCEEDED) { + pkg.mOperationPending = true; + } + } + } - public void movePackage(final String packageName, - final IPackageMoveObserver observer, final int flags) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MOVE_PACKAGE, null); - int returnCode = PackageManager.MOVE_SUCCEEDED; - int currFlags = 0; - int newFlags = 0; - synchronized (mPackages) { - PackageParser.Package pkg = mPackages.get(packageName); - if (pkg == null) { - returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; - } else { - // Disable moving fwd locked apps and system packages - if (pkg.applicationInfo != null && isSystemApp(pkg)) { - Slog.w(TAG, "Cannot move system application"); - returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE; - } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) { - Slog.w(TAG, "Cannot move forward locked app."); - returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED; - } else if (pkg.mOperationPending) { - Slog.w(TAG, "Attempt to move package which has pending operations"); - returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING; - } else { - // Find install location first - if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 && - (flags & PackageManager.MOVE_INTERNAL) != 0) { - Slog.w(TAG, "Ambigous flags specified for move location."); - returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; - } else { - newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? - PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL; - currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL - : PackageManager.INSTALL_INTERNAL; - if (newFlags == currFlags) { - Slog.w(TAG, "No move required. Trying to move to same location"); - returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; - } - } - if (returnCode == PackageManager.MOVE_SUCCEEDED) { - pkg.mOperationPending = true; - } - } - } - if (returnCode != PackageManager.MOVE_SUCCEEDED) { + /* + * TODO this next block probably shouldn't be inside the lock. We + * can't guarantee these won't change after this is fired off + * anyway. + */ + if (returnCode != PackageManager.MOVE_SUCCEEDED) { processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode); - } else { - Message msg = mHandler.obtainMessage(INIT_COPY); - InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, + } else { + Message msg = mHandler.obtainMessage(INIT_COPY); + InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir); - MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, + MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, pkg.applicationInfo.dataDir); - msg.obj = mp; - mHandler.sendMessage(msg); - } - } - } + msg.obj = mp; + mHandler.sendMessage(msg); + } + } + } - private void processPendingMove(final MoveParams mp, final int currentStatus) { - // Queue up an async operation since the package deletion may take a little while. - mHandler.post(new Runnable() { - public void run() { - mHandler.removeCallbacks(this); - int returnCode = currentStatus; - if (currentStatus == PackageManager.MOVE_SUCCEEDED) { - int uidArr[] = null; - ArrayList pkgList = null; - synchronized (mPackages) { - PackageParser.Package pkg = mPackages.get(mp.packageName); - if (pkg == null) { - Slog.w(TAG, " Package " + mp.packageName + - " doesn't exist. Aborting move"); - returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; - } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) { - Slog.w(TAG, "Package " + mp.packageName + " code path changed from " + - mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir + - " Aborting move and returning error"); - returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR; - } else { - uidArr = new int[] { pkg.applicationInfo.uid }; - pkgList = new ArrayList(); - pkgList.add(mp.packageName); - } - } - if (returnCode == PackageManager.MOVE_SUCCEEDED) { - // Send resources unavailable broadcast - sendResourcesChangedBroadcast(false, pkgList, uidArr, null); - // Update package code and resource paths - synchronized (mInstallLock) { - synchronized (mPackages) { - PackageParser.Package pkg = mPackages.get(mp.packageName); - // Recheck for package again. + private void processPendingMove(final MoveParams mp, final int currentStatus) { + // Queue up an async operation since the package deletion may take a + // little while. + mHandler.post(new Runnable() { + public void run() { + // TODO fix this; this does nothing. + mHandler.removeCallbacks(this); + int returnCode = currentStatus; + if (currentStatus == PackageManager.MOVE_SUCCEEDED) { + int uidArr[] = null; + ArrayList pkgList = null; + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(mp.packageName); + if (pkg == null) { + Slog.w(TAG, " Package " + mp.packageName + + " doesn't exist. Aborting move"); + returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; + } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) { + Slog.w(TAG, "Package " + mp.packageName + " code path changed from " + + mp.srcArgs.getCodePath() + " to " + + pkg.applicationInfo.sourceDir + + " Aborting move and returning error"); + returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR; + } else { + uidArr = new int[] { + pkg.applicationInfo.uid + }; + pkgList = new ArrayList(); + pkgList.add(mp.packageName); + } + } + if (returnCode == PackageManager.MOVE_SUCCEEDED) { + // Send resources unavailable broadcast + sendResourcesChangedBroadcast(false, pkgList, uidArr, null); + // Update package code and resource paths + synchronized (mInstallLock) { + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(mp.packageName); + // Recheck for package again. if (pkg == null) { Slog.w(TAG, " Package " + mp.packageName + " doesn't exist. Aborting move"); returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; - } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) { - Slog.w(TAG, "Package " + mp.packageName + " code path changed from " + - mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir + - " Aborting move and returning error"); - returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR; - } else { - final String oldCodePath = pkg.mPath; - final String newCodePath = mp.targetArgs.getCodePath(); - final String newResPath = mp.targetArgs.getResourcePath(); - final String newNativePath = mp.targetArgs.getNativeLibraryPath(); + } else if (!mp.srcArgs.getCodePath().equals( + pkg.applicationInfo.sourceDir)) { + Slog.w(TAG, "Package " + mp.packageName + + " code path changed from " + mp.srcArgs.getCodePath() + + " to " + pkg.applicationInfo.sourceDir + + " Aborting move and returning error"); + returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR; + } else { + final String oldCodePath = pkg.mPath; + final String newCodePath = mp.targetArgs.getCodePath(); + final String newResPath = mp.targetArgs.getResourcePath(); + final String newNativePath = mp.targetArgs + .getNativeLibraryPath(); if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) { if (mInstaller .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; } else { - NativeLibraryHelper.copyNativeBinariesLI( - new File(newCodePath), new File(newNativePath)); + NativeLibraryHelper.copyNativeBinariesLI(new File( + newCodePath), new File(newNativePath)); } } else { if (mInstaller.linkNativeLibraryDirectory( @@ -10416,90 +7922,92 @@ class PackageManagerService extends IPackageManager.Stub { } if (returnCode == PackageManager.MOVE_SUCCEEDED) { - pkg.mScanPath = newCodePath; - pkg.applicationInfo.sourceDir = newCodePath; - pkg.applicationInfo.publicSourceDir = newResPath; - pkg.applicationInfo.nativeLibraryDir = newNativePath; - PackageSetting ps = (PackageSetting) pkg.mExtras; - ps.codePath = new File(pkg.applicationInfo.sourceDir); - ps.codePathString = ps.codePath.getPath(); - ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir); - ps.resourcePathString = ps.resourcePath.getPath(); - ps.nativeLibraryPathString = newNativePath; - // Set the application info flag correctly. - if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) { - pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; - } else { - pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE; - } - ps.setFlags(pkg.applicationInfo.flags); - mAppDirs.remove(oldCodePath); - mAppDirs.put(newCodePath, pkg); - // Persist settings - mSettings.writeLP(); - } - } - } - } - // Send resources available broadcast - sendResourcesChangedBroadcast(true, pkgList, uidArr, null); - } - } - if (returnCode != PackageManager.MOVE_SUCCEEDED){ - // Clean up failed installation - if (mp.targetArgs != null) { - mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR); - } - } else { - // Force a gc to clear things up. - Runtime.getRuntime().gc(); - // Delete older code - synchronized (mInstallLock) { - mp.srcArgs.doPostDeleteLI(true); - } - } + pkg.mScanPath = newCodePath; + pkg.applicationInfo.sourceDir = newCodePath; + pkg.applicationInfo.publicSourceDir = newResPath; + pkg.applicationInfo.nativeLibraryDir = newNativePath; + PackageSetting ps = (PackageSetting) pkg.mExtras; + ps.codePath = new File(pkg.applicationInfo.sourceDir); + ps.codePathString = ps.codePath.getPath(); + ps.resourcePath = new File( + pkg.applicationInfo.publicSourceDir); + ps.resourcePathString = ps.resourcePath.getPath(); + ps.nativeLibraryPathString = newNativePath; + // Set the application info flag + // correctly. + if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; + } else { + pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE; + } + ps.setFlags(pkg.applicationInfo.flags); + mAppDirs.remove(oldCodePath); + mAppDirs.put(newCodePath, pkg); + // Persist settings + mSettings.writeLPr(); + } + } + } + } + // Send resources available broadcast + sendResourcesChangedBroadcast(true, pkgList, uidArr, null); + } + } + if (returnCode != PackageManager.MOVE_SUCCEEDED) { + // Clean up failed installation + if (mp.targetArgs != null) { + mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR); + } + } else { + // Force a gc to clear things up. + Runtime.getRuntime().gc(); + // Delete older code + synchronized (mInstallLock) { + mp.srcArgs.doPostDeleteLI(true); + } + } - // Allow more operations on this file if we didn't fail because - // an operation was already pending for this package. - if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) { - synchronized (mPackages) { - PackageParser.Package pkg = mPackages.get(mp.packageName); - if (pkg != null) { - pkg.mOperationPending = false; + // Allow more operations on this file if we didn't fail because + // an operation was already pending for this package. + if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) { + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(mp.packageName); + if (pkg != null) { + pkg.mOperationPending = false; } } - } + } - IPackageMoveObserver observer = mp.observer; - if (observer != null) { - try { - observer.packageMoved(mp.packageName, returnCode); - } catch (RemoteException e) { - Log.i(TAG, "Observer no longer exists."); - } - } - } - }); + IPackageMoveObserver observer = mp.observer; + if (observer != null) { + try { + observer.packageMoved(mp.packageName, returnCode); + } catch (RemoteException e) { + Log.i(TAG, "Observer no longer exists."); + } + } + } + }); + } + + public boolean setInstallLocation(int loc) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, + null); + if (getInstallLocation() == loc) { + return true; + } + if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL + || loc == PackageHelper.APP_INSTALL_EXTERNAL) { + android.provider.Settings.System.putInt(mContext.getContentResolver(), + android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc); + return true; + } + return false; } - public boolean setInstallLocation(int loc) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WRITE_SECURE_SETTINGS, null); - if (getInstallLocation() == loc) { - return true; - } - if (loc == PackageHelper.APP_INSTALL_AUTO || - loc == PackageHelper.APP_INSTALL_INTERNAL || - loc == PackageHelper.APP_INSTALL_EXTERNAL) { - android.provider.Settings.System.putInt(mContext.getContentResolver(), - android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc); - return true; - } - return false; - } - - public int getInstallLocation() { - return android.provider.Settings.System.getInt(mContext.getContentResolver(), - android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO); - } + public int getInstallLocation() { + return android.provider.Settings.System.getInt(mContext.getContentResolver(), + android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, + PackageHelper.APP_INSTALL_AUTO); + } } diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/java/com/android/server/pm/PackageSetting.java new file mode 100644 index 0000000000000..efdc2b3bdfe17 --- /dev/null +++ b/services/java/com/android/server/pm/PackageSetting.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.PackageParser; + +import java.io.File; + +/** + * Settings data for a particular package we know about. + */ +final class PackageSetting extends PackageSettingBase { + int userId; + PackageParser.Package pkg; + SharedUserSetting sharedUser; + + PackageSetting(String name, String realName, File codePath, File resourcePath, + String nativeLibraryPathString, int pVersionCode, int pkgFlags) { + super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode, + pkgFlags); + } + + /** + * New instance of PackageSetting replicating the original settings. + * Note that it keeps the same PackageParser.Package instance. + */ + PackageSetting(PackageSetting orig) { + super(orig); + + userId = orig.userId; + pkg = orig.pkg; + sharedUser = orig.sharedUser; + } + + @Override + public String toString() { + return "PackageSetting{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + name + "/" + userId + "}"; + } +} \ No newline at end of file diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java new file mode 100644 index 0000000000000..e2f83adda16b9 --- /dev/null +++ b/services/java/com/android/server/pm/PackageSettingBase.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; + + +import java.io.File; +import java.util.HashSet; + +/** + * Settings base class for pending and resolved classes. + */ +class PackageSettingBase extends GrantedPermissions { + /** + * Indicates the state of installation. Used by PackageManager to figure out + * incomplete installations. Say a package is being installed (the state is + * set to PKG_INSTALL_INCOMPLETE) and remains so till the package + * installation is successful or unsuccessful in which case the + * PackageManager will no longer maintain state information associated with + * the package. If some exception(like device freeze or battery being pulled + * out) occurs during installation of a package, the PackageManager needs + * this information to clean up the previously failed installation. + */ + static final int PKG_INSTALL_COMPLETE = 1; + static final int PKG_INSTALL_INCOMPLETE = 0; + + final String name; + final String realName; + File codePath; + String codePathString; + File resourcePath; + String resourcePathString; + String nativeLibraryPathString; + long timeStamp; + long firstInstallTime; + long lastUpdateTime; + int versionCode; + + boolean uidError; + + PackageSignatures signatures = new PackageSignatures(); + + boolean permissionsFixed; + boolean haveGids; + + // Whether this package is currently stopped, thus can not be + // started until explicitly launched by the user. + public boolean stopped; + + // Set to true if we have never launched this app. + public boolean notLaunched; + + /* Explicitly disabled components */ + HashSet disabledComponents = new HashSet(0); + /* Explicitly enabled components */ + HashSet enabledComponents = new HashSet(0); + int enabled = COMPONENT_ENABLED_STATE_DEFAULT; + int installStatus = PKG_INSTALL_COMPLETE; + + PackageSettingBase origPackage; + + /* package name of the app that installed this package */ + String installerPackageName; + PackageSettingBase(String name, String realName, File codePath, File resourcePath, + String nativeLibraryPathString, int pVersionCode, int pkgFlags) { + super(pkgFlags); + this.name = name; + this.realName = realName; + init(codePath, resourcePath, nativeLibraryPathString, pVersionCode); + } + + /** + * New instance of PackageSetting with one-level-deep cloning. + */ + @SuppressWarnings("unchecked") + PackageSettingBase(PackageSettingBase base) { + super(base); + + name = base.name; + realName = base.realName; + codePath = base.codePath; + codePathString = base.codePathString; + resourcePath = base.resourcePath; + resourcePathString = base.resourcePathString; + nativeLibraryPathString = base.nativeLibraryPathString; + timeStamp = base.timeStamp; + firstInstallTime = base.firstInstallTime; + lastUpdateTime = base.lastUpdateTime; + versionCode = base.versionCode; + + uidError = base.uidError; + + signatures = new PackageSignatures(base.signatures); + + permissionsFixed = base.permissionsFixed; + haveGids = base.haveGids; + stopped = base.stopped; + notLaunched = base.notLaunched; + + disabledComponents = (HashSet) base.disabledComponents.clone(); + + enabledComponents = (HashSet) base.enabledComponents.clone(); + + enabled = base.enabled; + installStatus = base.installStatus; + + origPackage = base.origPackage; + + installerPackageName = base.installerPackageName; + } + + void init(File codePath, File resourcePath, String nativeLibraryPathString, + int pVersionCode) { + this.codePath = codePath; + this.codePathString = codePath.toString(); + this.resourcePath = resourcePath; + this.resourcePathString = resourcePath.toString(); + this.nativeLibraryPathString = nativeLibraryPathString; + this.versionCode = pVersionCode; + } + + public void setInstallerPackageName(String packageName) { + installerPackageName = packageName; + } + + String getInstallerPackageName() { + return installerPackageName; + } + + public void setInstallStatus(int newStatus) { + installStatus = newStatus; + } + + public int getInstallStatus() { + return installStatus; + } + + public void setTimeStamp(long newStamp) { + timeStamp = newStamp; + } + + /** + * Make a shallow copy of this package settings. + */ + public void copyFrom(PackageSettingBase base) { + grantedPermissions = base.grantedPermissions; + gids = base.gids; + + timeStamp = base.timeStamp; + firstInstallTime = base.firstInstallTime; + lastUpdateTime = base.lastUpdateTime; + signatures = base.signatures; + permissionsFixed = base.permissionsFixed; + haveGids = base.haveGids; + stopped = base.stopped; + notLaunched = base.notLaunched; + disabledComponents = base.disabledComponents; + enabledComponents = base.enabledComponents; + enabled = base.enabled; + installStatus = base.installStatus; + } + + boolean enableComponentLPw(String componentClassName) { + boolean changed = disabledComponents.remove(componentClassName); + changed |= enabledComponents.add(componentClassName); + return changed; + } + + boolean disableComponentLPw(String componentClassName) { + boolean changed = enabledComponents.remove(componentClassName); + changed |= disabledComponents.add(componentClassName); + return changed; + } + + boolean restoreComponentLPw(String componentClassName) { + boolean changed = enabledComponents.remove(componentClassName); + changed |= disabledComponents.remove(componentClassName); + return changed; + } + + int getCurrentEnabledStateLPr(String componentName) { + if (enabledComponents.contains(componentName)) { + return COMPONENT_ENABLED_STATE_ENABLED; + } else if (disabledComponents.contains(componentName)) { + return COMPONENT_ENABLED_STATE_DISABLED; + } else { + return COMPONENT_ENABLED_STATE_DEFAULT; + } + } +} \ No newline at end of file diff --git a/services/java/com/android/server/pm/PackageSignatures.java b/services/java/com/android/server/pm/PackageSignatures.java new file mode 100644 index 0000000000000..a25ec6cee5082 --- /dev/null +++ b/services/java/com/android/server/pm/PackageSignatures.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import android.content.pm.Signature; +import android.util.Log; + +import java.io.IOException; +import java.util.ArrayList; + +class PackageSignatures { + Signature[] mSignatures; + + PackageSignatures(PackageSignatures orig) { + if (orig != null && orig.mSignatures != null) { + mSignatures = orig.mSignatures.clone(); + } + } + + PackageSignatures(Signature[] sigs) { + assignSignatures(sigs); + } + + PackageSignatures() { + } + + void writeXml(XmlSerializer serializer, String tagName, + ArrayList pastSignatures) throws IOException { + if (mSignatures == null) { + return; + } + serializer.startTag(null, tagName); + serializer.attribute(null, "count", + Integer.toString(mSignatures.length)); + for (int i=0; i= numPast) { + pastSignatures.add(sig); + serializer.attribute(null, "index", Integer.toString(numPast)); + serializer.attribute(null, "key", sig.toCharsString()); + } + serializer.endTag(null, "cert"); + } + serializer.endTag(null, tagName); + } + + void readXml(XmlPullParser parser, ArrayList pastSignatures) + throws IOException, XmlPullParserException { + String countStr = parser.getAttributeValue(null, "count"); + if (countStr == null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has" + + " no count at " + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + } + final int count = Integer.parseInt(countStr); + mSignatures = new Signature[count]; + int pos = 0; + + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG + || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("cert")) { + if (pos < count) { + String index = parser.getAttributeValue(null, "index"); + if (index != null) { + try { + int idx = Integer.parseInt(index); + String key = parser.getAttributeValue(null, "key"); + if (key == null) { + if (idx >= 0 && idx < pastSignatures.size()) { + Signature sig = pastSignatures.get(idx); + if (sig != null) { + mSignatures[pos] = pastSignatures.get(idx); + pos++; + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: " + + "index " + index + " is not defined at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: " + + "index " + index + " is out of bounds at " + + parser.getPositionDescription()); + } + } else { + while (pastSignatures.size() <= idx) { + pastSignatures.add(null); + } + Signature sig = new Signature(key); + pastSignatures.set(idx, sig); + mSignatures[pos] = sig; + pos++; + } + } catch (NumberFormatException e) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: " + + "index " + index + " is not a number at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has" + + " no index at " + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: too " + + "many tags, expected " + count + + " at " + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + + parser.getName()); + } + XmlUtils.skipCurrentTag(parser); + } + + if (pos < count) { + // Should never happen -- there is an error in the written + // settings -- but if it does we don't want to generate + // a bad array. + Signature[] newSigs = new Signature[pos]; + System.arraycopy(mSignatures, 0, newSigs, 0, pos); + mSignatures = newSigs; + } + } + + void assignSignatures(Signature[] sigs) { + if (sigs == null) { + mSignatures = null; + return; + } + mSignatures = new Signature[sigs.length]; + for (int i=0; i 0) buf.append(", "); + buf.append(Integer.toHexString( + System.identityHashCode(mSignatures[i]))); + } + } + buf.append("]}"); + return buf.toString(); + } +} \ No newline at end of file diff --git a/services/java/com/android/server/pm/PendingPackage.java b/services/java/com/android/server/pm/PendingPackage.java new file mode 100644 index 0000000000000..c17cc46dbfb58 --- /dev/null +++ b/services/java/com/android/server/pm/PendingPackage.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import java.io.File; + +final class PendingPackage extends PackageSettingBase { + final int sharedId; + + PendingPackage(String name, String realName, File codePath, File resourcePath, + String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) { + super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode, + pkgFlags); + this.sharedId = sharedId; + } +} diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java new file mode 100644 index 0000000000000..b100eb1621ef9 --- /dev/null +++ b/services/java/com/android/server/pm/PreferredActivity.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import com.android.internal.util.XmlUtils; +import com.android.server.PreferredComponent; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import android.content.ComponentName; +import android.content.IntentFilter; +import android.util.Log; + +import java.io.IOException; + +class PreferredActivity extends IntentFilter implements PreferredComponent.Callbacks { + private static final String TAG = "PreferredActivity"; + + private static final boolean DEBUG_FILTERS = false; + + final PreferredComponent mPref; + + PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { + super(filter); + mPref = new PreferredComponent(this, match, set, activity); + } + + PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException { + mPref = new PreferredComponent(this, parser); + } + + public void writeToXml(XmlSerializer serializer) throws IOException { + mPref.writeToXml(serializer); + serializer.startTag(null, "filter"); + super.writeToXml(serializer); + serializer.endTag(null, "filter"); + } + + public boolean onReadTag(String tagName, XmlPullParser parser) throws XmlPullParserException, + IOException { + if (tagName.equals("filter")) { + if (DEBUG_FILTERS) { + Log.i(TAG, "Starting to parse filter..."); + } + readFromXml(parser); + if (DEBUG_FILTERS) { + Log.i(TAG, "Finished filter: depth=" + parser.getDepth() + " tag=" + + parser.getName()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + return true; + } +} diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java new file mode 100644 index 0000000000000..11dde752272c5 --- /dev/null +++ b/services/java/com/android/server/pm/Settings.java @@ -0,0 +1,2224 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; + +import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.JournaledFile; +import com.android.internal.util.XmlUtils; +import com.android.server.IntentResolver; +import com.android.server.pm.PackageManagerService.DumpState; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.ComponentInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.PermissionInfo; +import android.content.pm.Signature; +import android.os.Binder; +import android.os.Environment; +import android.os.FileUtils; +import android.os.Process; +import android.util.Log; +import android.util.Slog; +import android.util.SparseArray; +import android.util.Xml; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +/** + * Holds information about dynamic settings. + */ +final class Settings { + private static final String TAG = "PackageSettings"; + + private static final boolean DEBUG_STOPPED = false; + + private final File mSettingsFilename; + private final File mBackupSettingsFilename; + private final File mPackageListFilename; + private final File mStoppedPackagesFilename; + private final File mBackupStoppedPackagesFilename; + final HashMap mPackages = + new HashMap(); + // List of replaced system applications + final HashMap mDisabledSysPackages = + new HashMap(); + + // These are the last platform API version we were using for + // the apps installed on internal and external storage. It is + // used to grant newer permissions one time during a system upgrade. + int mInternalSdkPlatform; + int mExternalSdkPlatform; + + // The user's preferred activities associated with particular intent + // filters. + final IntentResolver mPreferredActivities = + new IntentResolver() { + @Override + protected String packageForFilter(PreferredActivity filter) { + return filter.mPref.mComponent.getPackageName(); + } + @Override + protected void dumpFilter(PrintWriter out, String prefix, + PreferredActivity filter) { + filter.mPref.dump(out, prefix, filter); + } + }; + final HashMap mSharedUsers = + new HashMap(); + private final ArrayList mUserIds = new ArrayList(); + private final SparseArray mOtherUserIds = + new SparseArray(); + + // For reading/writing settings file. + private final ArrayList mPastSignatures = + new ArrayList(); + + // Mapping from permission names to info about them. + final HashMap mPermissions = + new HashMap(); + + // Mapping from permission tree names to info about them. + final HashMap mPermissionTrees = + new HashMap(); + + // Packages that have been uninstalled and still need their external + // storage data deleted. + final ArrayList mPackagesToBeCleaned = new ArrayList(); + + // Packages that have been renamed since they were first installed. + // Keys are the new names of the packages, values are the original + // names. The packages appear everwhere else under their original + // names. + final HashMap mRenamedPackages = new HashMap(); + + final StringBuilder mReadMessages = new StringBuilder(); + + /** + * Used to track packages that have a shared user ID that hasn't been read + * in yet. + *

+ * TODO: make this just a local variable that is passed in during package + * scanning to make it less confusing. + */ + private final ArrayList mPendingPackages = new ArrayList(); + + Settings() { + File dataDir = Environment.getDataDirectory(); + File systemDir = new File(dataDir, "system"); + // TODO(oam): This secure dir creation needs to be moved somewhere else (later) + File systemSecureDir = new File(dataDir, "secure/system"); + systemDir.mkdirs(); + systemSecureDir.mkdirs(); + FileUtils.setPermissions(systemDir.toString(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG + |FileUtils.S_IROTH|FileUtils.S_IXOTH, + -1, -1); + FileUtils.setPermissions(systemSecureDir.toString(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG + |FileUtils.S_IROTH|FileUtils.S_IXOTH, + -1, -1); + mSettingsFilename = new File(systemDir, "packages.xml"); + mBackupSettingsFilename = new File(systemDir, "packages-backup.xml"); + mPackageListFilename = new File(systemDir, "packages.list"); + mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml"); + mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml"); + } + + PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage, + String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, + String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) { + final String name = pkg.packageName; + PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath, + resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add); + return p; + } + + PackageSetting peekPackageLPr(String name) { + return mPackages.get(name); + } + + void setInstallStatus(String pkgName, int status) { + PackageSetting p = mPackages.get(pkgName); + if(p != null) { + if(p.getInstallStatus() != status) { + p.setInstallStatus(status); + } + } + } + + void setInstallerPackageName(String pkgName, + String installerPkgName) { + PackageSetting p = mPackages.get(pkgName); + if(p != null) { + p.setInstallerPackageName(installerPkgName); + } + } + + SharedUserSetting getSharedUserLPw(String name, + int pkgFlags, boolean create) { + SharedUserSetting s = mSharedUsers.get(name); + if (s == null) { + if (!create) { + return null; + } + s = new SharedUserSetting(name, pkgFlags); + if (PackageManagerService.MULTIPLE_APPLICATION_UIDS) { + s.userId = newUserIdLPw(s); + } else { + s.userId = PackageManagerService.FIRST_APPLICATION_UID; + } + Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId); + // < 0 means we couldn't assign a userid; fall out and return + // s, which is currently null + if (s.userId >= 0) { + mSharedUsers.put(name, s); + } + } + + return s; + } + + boolean disableSystemPackageLPw(String name) { + final PackageSetting p = mPackages.get(name); + if(p == null) { + Log.w(PackageManagerService.TAG, "Package:"+name+" is not an installed package"); + return false; + } + final PackageSetting dp = mDisabledSysPackages.get(name); + // always make sure the system package code and resource paths dont change + if (dp == null) { + if((p.pkg != null) && (p.pkg.applicationInfo != null)) { + p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + } + mDisabledSysPackages.put(name, p); + + // a little trick... when we install the new package, we don't + // want to modify the existing PackageSetting for the built-in + // version. so at this point we need a new PackageSetting that + // is okay to muck with. + PackageSetting newp = new PackageSetting(p); + replacePackageLPw(name, newp); + return true; + } + return false; + } + + PackageSetting enableSystemPackageLPw(String name) { + PackageSetting p = mDisabledSysPackages.get(name); + if(p == null) { + Log.w(PackageManagerService.TAG, "Package:"+name+" is not disabled"); + return null; + } + // Reset flag in ApplicationInfo object + if((p.pkg != null) && (p.pkg.applicationInfo != null)) { + p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + } + PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath, + p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags); + mDisabledSysPackages.remove(name); + return ret; + } + + PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath, + String nativeLibraryPathString, int uid, int vc, int pkgFlags) { + PackageSetting p = mPackages.get(name); + if (p != null) { + if (p.userId == uid) { + return p; + } + PackageManagerService.reportSettingsProblem(Log.ERROR, + "Adding duplicate package, keeping first: " + name); + return null; + } + p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, + vc, pkgFlags); + p.userId = uid; + if (addUserIdLPw(uid, p, name)) { + mPackages.put(name, p); + return p; + } + return null; + } + + SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) { + SharedUserSetting s = mSharedUsers.get(name); + if (s != null) { + if (s.userId == uid) { + return s; + } + PackageManagerService.reportSettingsProblem(Log.ERROR, + "Adding duplicate shared user, keeping first: " + name); + return null; + } + s = new SharedUserSetting(name, pkgFlags); + s.userId = uid; + if (addUserIdLPw(uid, s, name)) { + mSharedUsers.put(name, s); + return s; + } + return null; + } + + // Transfer ownership of permissions from one package to another. + void transferPermissionsLPw(String origPkg, String newPkg) { + // Transfer ownership of permissions to the new package. + for (int i=0; i<2; i++) { + HashMap permissions = + i == 0 ? mPermissionTrees : mPermissions; + for (BasePermission bp : permissions.values()) { + if (origPkg.equals(bp.sourcePackage)) { + if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, + "Moving permission " + bp.name + + " from pkg " + bp.sourcePackage + + " to " + newPkg); + bp.sourcePackage = newPkg; + bp.packageSetting = null; + bp.perm = null; + if (bp.pendingInfo != null) { + bp.pendingInfo.packageName = newPkg; + } + bp.uid = 0; + bp.gids = null; + } + } + } + } + + private PackageSetting getPackageLPw(String name, PackageSetting origPackage, + String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, + String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) { + PackageSetting p = mPackages.get(name); + if (p != null) { + if (!p.codePath.equals(codePath)) { + // Check to see if its a disabled system app + if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { + // This is an updated system app with versions in both system + // and data partition. Just let the most recent version + // take precedence. + Slog.w(PackageManagerService.TAG, "Trying to update system app code path from " + + p.codePathString + " to " + codePath.toString()); + } else { + // Just a change in the code path is not an issue, but + // let's log a message about it. + Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from " + p.codePath + + " to " + codePath + "; Retaining data and using new"); + /* + * Since we've changed paths, we need to prefer the new + * native library path over the one stored in the + * package settings since we might have moved from + * internal to external storage or vice versa. + */ + p.nativeLibraryPathString = nativeLibraryPathString; + } + } + if (p.sharedUser != sharedUser) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Package " + name + " shared user changed from " + + (p.sharedUser != null ? p.sharedUser.name : "") + + " to " + + (sharedUser != null ? sharedUser.name : "") + + "; replacing with new"); + p = null; + } else { + if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) { + // If what we are scanning is a system package, then + // make it so, regardless of whether it was previously + // installed only in the data partition. + p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM; + } + } + } + if (p == null) { + // Create a new PackageSettings entry. this can end up here because + // of code path mismatch or user id mismatch of an updated system partition + if (!create) { + return null; + } + if (origPackage != null) { + // We are consuming the data from an existing package. + p = new PackageSetting(origPackage.name, name, codePath, resourcePath, + nativeLibraryPathString, vc, pkgFlags); + if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name + + " is adopting original package " + origPackage.name); + // Note that we will retain the new package's signature so + // that we can keep its data. + PackageSignatures s = p.signatures; + p.copyFrom(origPackage); + p.signatures = s; + p.sharedUser = origPackage.sharedUser; + p.userId = origPackage.userId; + p.origPackage = origPackage; + mRenamedPackages.put(name, origPackage.name); + name = origPackage.name; + // Update new package state. + p.setTimeStamp(codePath.lastModified()); + } else { + p = new PackageSetting(name, realName, codePath, resourcePath, + nativeLibraryPathString, vc, pkgFlags); + p.setTimeStamp(codePath.lastModified()); + p.sharedUser = sharedUser; + // If this is not a system app, it starts out stopped. + if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { + if (DEBUG_STOPPED) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(PackageManagerService.TAG, "Stopping package " + name, e); + } + p.stopped = true; + p.notLaunched = true; + } + if (sharedUser != null) { + p.userId = sharedUser.userId; + } else if (PackageManagerService.MULTIPLE_APPLICATION_UIDS) { + // Clone the setting here for disabled system packages + PackageSetting dis = mDisabledSysPackages.get(name); + if (dis != null) { + // For disabled packages a new setting is created + // from the existing user id. This still has to be + // added to list of user id's + // Copy signatures from previous setting + if (dis.signatures.mSignatures != null) { + p.signatures.mSignatures = dis.signatures.mSignatures.clone(); + } + p.userId = dis.userId; + // Clone permissions + p.grantedPermissions = new HashSet(dis.grantedPermissions); + // Clone component info + p.disabledComponents = new HashSet(dis.disabledComponents); + p.enabledComponents = new HashSet(dis.enabledComponents); + // Add new setting to list of user ids + addUserIdLPw(p.userId, p, name); + } else { + // Assign new user id + p.userId = newUserIdLPw(p); + } + } else { + p.userId = PackageManagerService.FIRST_APPLICATION_UID; + } + } + if (p.userId < 0) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Package " + name + " could not be assigned a valid uid"); + return null; + } + if (add) { + // Finish adding new package by adding it and updating shared + // user preferences + addPackageSettingLPw(p, name, sharedUser); + } + } + return p; + } + + void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) { + p.pkg = pkg; + pkg.mSetEnabled = p.enabled; + pkg.mSetStopped = p.stopped; + final String codePath = pkg.applicationInfo.sourceDir; + final String resourcePath = pkg.applicationInfo.publicSourceDir; + // Update code path if needed + if (!codePath.equalsIgnoreCase(p.codePathString)) { + Slog.w(PackageManagerService.TAG, "Code path for pkg : " + p.pkg.packageName + + " changing from " + p.codePathString + " to " + codePath); + p.codePath = new File(codePath); + p.codePathString = codePath; + } + //Update resource path if needed + if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) { + Slog.w(PackageManagerService.TAG, "Resource path for pkg : " + p.pkg.packageName + + " changing from " + p.resourcePathString + " to " + resourcePath); + p.resourcePath = new File(resourcePath); + p.resourcePathString = resourcePath; + } + // Update the native library path if needed + final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir; + if (nativeLibraryPath != null + && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) { + p.nativeLibraryPathString = nativeLibraryPath; + } + // Update version code if needed + if (pkg.mVersionCode != p.versionCode) { + p.versionCode = pkg.mVersionCode; + } + // Update signatures if needed. + if (p.signatures.mSignatures == null) { + p.signatures.assignSignatures(pkg.mSignatures); + } + // If this app defines a shared user id initialize + // the shared user signatures as well. + if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) { + p.sharedUser.signatures.assignSignatures(pkg.mSignatures); + } + addPackageSettingLPw(p, pkg.packageName, p.sharedUser); + } + + // Utility method that adds a PackageSetting to mPackages and + // completes updating the shared user attributes + private void addPackageSettingLPw(PackageSetting p, String name, + SharedUserSetting sharedUser) { + mPackages.put(name, p); + if (sharedUser != null) { + if (p.sharedUser != null && p.sharedUser != sharedUser) { + PackageManagerService.reportSettingsProblem(Log.ERROR, + "Package " + p.name + " was user " + + p.sharedUser + " but is now " + sharedUser + + "; I am not changing its files so it will probably fail!"); + p.sharedUser.packages.remove(p); + } else if (p.userId != sharedUser.userId) { + PackageManagerService.reportSettingsProblem(Log.ERROR, + "Package " + p.name + " was user id " + p.userId + + " but is now user " + sharedUser + + " with id " + sharedUser.userId + + "; I am not changing its files so it will probably fail!"); + } + + sharedUser.packages.add(p); + p.sharedUser = sharedUser; + p.userId = sharedUser.userId; + } + } + + /* + * Update the shared user setting when a package using + * specifying the shared user id is removed. The gids + * associated with each permission of the deleted package + * are removed from the shared user's gid list only if its + * not in use by other permissions of packages in the + * shared user setting. + */ + void updateSharedUserPermsLPw(PackageSetting deletedPs, int[] globalGids) { + if ((deletedPs == null) || (deletedPs.pkg == null)) { + Slog.i(PackageManagerService.TAG, + "Trying to update info for null package. Just ignoring"); + return; + } + // No sharedUserId + if (deletedPs.sharedUser == null) { + return; + } + SharedUserSetting sus = deletedPs.sharedUser; + // Update permissions + for (String eachPerm : deletedPs.pkg.requestedPermissions) { + boolean used = false; + if (!sus.grantedPermissions.contains(eachPerm)) { + continue; + } + for (PackageSetting pkg:sus.packages) { + if (pkg.pkg != null && + !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) && + pkg.pkg.requestedPermissions.contains(eachPerm)) { + used = true; + break; + } + } + if (!used) { + // can safely delete this permission from list + sus.grantedPermissions.remove(eachPerm); + } + } + // Update gids + int newGids[] = globalGids; + for (String eachPerm : sus.grantedPermissions) { + BasePermission bp = mPermissions.get(eachPerm); + if (bp != null) { + newGids = PackageManagerService.appendInts(newGids, bp.gids); + } + } + sus.gids = newGids; + } + + int removePackageLPw(String name) { + final PackageSetting p = mPackages.get(name); + if (p != null) { + mPackages.remove(name); + if (p.sharedUser != null) { + p.sharedUser.packages.remove(p); + if (p.sharedUser.packages.size() == 0) { + mSharedUsers.remove(p.sharedUser.name); + removeUserIdLPw(p.sharedUser.userId); + return p.sharedUser.userId; + } + } else { + removeUserIdLPw(p.userId); + return p.userId; + } + } + return -1; + } + + private void replacePackageLPw(String name, PackageSetting newp) { + final PackageSetting p = mPackages.get(name); + if (p != null) { + if (p.sharedUser != null) { + p.sharedUser.packages.remove(p); + p.sharedUser.packages.add(newp); + } else { + replaceUserIdLPw(p.userId, newp); + } + } + mPackages.put(name, newp); + } + + private boolean addUserIdLPw(int uid, Object obj, Object name) { + if (uid >= PackageManagerService.FIRST_APPLICATION_UID + PackageManagerService.MAX_APPLICATION_UIDS) { + return false; + } + + if (uid >= PackageManagerService.FIRST_APPLICATION_UID) { + int N = mUserIds.size(); + final int index = uid - PackageManagerService.FIRST_APPLICATION_UID; + while (index >= N) { + mUserIds.add(null); + N++; + } + if (mUserIds.get(index) != null) { + PackageManagerService.reportSettingsProblem(Log.ERROR, + "Adding duplicate user id: " + uid + + " name=" + name); + return false; + } + mUserIds.set(index, obj); + } else { + if (mOtherUserIds.get(uid) != null) { + PackageManagerService.reportSettingsProblem(Log.ERROR, + "Adding duplicate shared id: " + uid + + " name=" + name); + return false; + } + mOtherUserIds.put(uid, obj); + } + return true; + } + + public Object getUserIdLPr(int uid) { + if (uid >= PackageManagerService.FIRST_APPLICATION_UID) { + final int N = mUserIds.size(); + final int index = uid - PackageManagerService.FIRST_APPLICATION_UID; + return index < N ? mUserIds.get(index) : null; + } else { + return mOtherUserIds.get(uid); + } + } + + private void removeUserIdLPw(int uid) { + if (uid >= PackageManagerService.FIRST_APPLICATION_UID) { + final int N = mUserIds.size(); + final int index = uid - PackageManagerService.FIRST_APPLICATION_UID; + if (index < N) mUserIds.set(index, null); + } else { + mOtherUserIds.remove(uid); + } + } + + private void replaceUserIdLPw(int uid, Object obj) { + if (uid >= PackageManagerService.FIRST_APPLICATION_UID) { + final int N = mUserIds.size(); + final int index = uid - PackageManagerService.FIRST_APPLICATION_UID; + if (index < N) mUserIds.set(index, obj); + } else { + mOtherUserIds.put(uid, obj); + } + } + + void writeStoppedLPr() { + // Keep the old stopped packages around until we know the new ones have + // been successfully written. + if (mStoppedPackagesFilename.exists()) { + // Presence of backup settings file indicates that we failed + // to persist packages earlier. So preserve the older + // backup for future reference since the current packages + // might have been corrupted. + if (!mBackupStoppedPackagesFilename.exists()) { + if (!mStoppedPackagesFilename.renameTo(mBackupStoppedPackagesFilename)) { + Log.wtf(PackageManagerService.TAG, "Unable to backup package manager stopped packages, " + + "current changes will be lost at reboot"); + return; + } + } else { + mStoppedPackagesFilename.delete(); + Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup"); + } + } + + try { + final FileOutputStream fstr = new FileOutputStream(mStoppedPackagesFilename); + final BufferedOutputStream str = new BufferedOutputStream(fstr); + + //XmlSerializer serializer = XmlUtils.serializerInstance(); + final XmlSerializer serializer = new FastXmlSerializer(); + serializer.setOutput(str, "utf-8"); + serializer.startDocument(null, true); + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); + + serializer.startTag(null, "stopped-packages"); + + for (final PackageSetting pkg : mPackages.values()) { + if (pkg.stopped) { + serializer.startTag(null, "pkg"); + serializer.attribute(null, "name", pkg.name); + if (pkg.notLaunched) { + serializer.attribute(null, "nl", "1"); + } + serializer.endTag(null, "pkg"); + } + } + + serializer.endTag(null, "stopped-packages"); + + serializer.endDocument(); + + str.flush(); + FileUtils.sync(fstr); + str.close(); + + // New settings successfully written, old ones are no longer + // needed. + mBackupStoppedPackagesFilename.delete(); + FileUtils.setPermissions(mStoppedPackagesFilename.toString(), + FileUtils.S_IRUSR|FileUtils.S_IWUSR + |FileUtils.S_IRGRP|FileUtils.S_IWGRP + |FileUtils.S_IROTH, + -1, -1); + + // Done, all is good! + return; + } catch(java.io.IOException e) { + Log.wtf(PackageManagerService.TAG, "Unable to write package manager stopped packages, " + + " current changes will be lost at reboot", e); + } + + // Clean up partially written files + if (mStoppedPackagesFilename.exists()) { + if (!mStoppedPackagesFilename.delete()) { + Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: " + mStoppedPackagesFilename); + } + } + } + + // Note: assumed "stopped" field is already cleared in all packages. + void readStoppedLPw() { + FileInputStream str = null; + if (mBackupStoppedPackagesFilename.exists()) { + try { + str = new FileInputStream(mBackupStoppedPackagesFilename); + mReadMessages.append("Reading from backup stopped packages file\n"); + PackageManagerService.reportSettingsProblem(Log.INFO, "Need to read from backup stopped packages file"); + if (mSettingsFilename.exists()) { + // If both the backup and normal file exist, we + // ignore the normal one since it might have been + // corrupted. + Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file " + + mStoppedPackagesFilename); + mStoppedPackagesFilename.delete(); + } + } catch (java.io.IOException e) { + // We'll try for the normal settings file. + } + } + + try { + if (str == null) { + if (!mStoppedPackagesFilename.exists()) { + mReadMessages.append("No stopped packages file found\n"); + PackageManagerService.reportSettingsProblem(Log.INFO, "No stopped packages file file; " + + "assuming all started"); + // At first boot, make sure no packages are stopped. + // We usually want to have third party apps initialize + // in the stopped state, but not at first boot. + for (PackageSetting pkg : mPackages.values()) { + pkg.stopped = false; + pkg.notLaunched = false; + } + return; + } + str = new FileInputStream(mStoppedPackagesFilename); + } + final XmlPullParser parser = Xml.newPullParser(); + parser.setInput(str, null); + + int type; + while ((type=parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + ; + } + + if (type != XmlPullParser.START_TAG) { + mReadMessages.append("No start tag found in stopped packages file\n"); + PackageManagerService.reportSettingsProblem(Log.WARN, + "No start tag found in package manager stopped packages"); + return; + } + + int outerDepth = parser.getDepth(); + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG + || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("pkg")) { + String name = parser.getAttributeValue(null, "name"); + PackageSetting ps = mPackages.get(name); + if (ps != null) { + ps.stopped = true; + if ("1".equals(parser.getAttributeValue(null, "nl"))) { + ps.notLaunched = true; + } + } else { + Slog.w(PackageManagerService.TAG, "No package known for stopped package: " + name); + } + XmlUtils.skipCurrentTag(parser); + } else { + Slog.w(PackageManagerService.TAG, "Unknown element under : " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + str.close(); + + } catch(XmlPullParserException e) { + mReadMessages.append("Error reading: " + e.toString()); + PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading stopped packages: " + e); + Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e); + + } catch(java.io.IOException e) { + mReadMessages.append("Error reading: " + e.toString()); + PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); + Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e); + + } + } + + void writeLPr() { + //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024); + + // Keep the old settings around until we know the new ones have + // been successfully written. + if (mSettingsFilename.exists()) { + // Presence of backup settings file indicates that we failed + // to persist settings earlier. So preserve the older + // backup for future reference since the current settings + // might have been corrupted. + if (!mBackupSettingsFilename.exists()) { + if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) { + Log.wtf(PackageManagerService.TAG, "Unable to backup package manager settings, " + + " current changes will be lost at reboot"); + return; + } + } else { + mSettingsFilename.delete(); + Slog.w(PackageManagerService.TAG, "Preserving older settings backup"); + } + } + + mPastSignatures.clear(); + + try { + FileOutputStream fstr = new FileOutputStream(mSettingsFilename); + BufferedOutputStream str = new BufferedOutputStream(fstr); + + //XmlSerializer serializer = XmlUtils.serializerInstance(); + XmlSerializer serializer = new FastXmlSerializer(); + serializer.setOutput(str, "utf-8"); + serializer.startDocument(null, true); + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); + + serializer.startTag(null, "packages"); + + serializer.startTag(null, "last-platform-version"); + serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform)); + serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform)); + serializer.endTag(null, "last-platform-version"); + + serializer.startTag(null, "permission-trees"); + for (BasePermission bp : mPermissionTrees.values()) { + writePermissionLPr(serializer, bp); + } + serializer.endTag(null, "permission-trees"); + + serializer.startTag(null, "permissions"); + for (BasePermission bp : mPermissions.values()) { + writePermissionLPr(serializer, bp); + } + serializer.endTag(null, "permissions"); + + for (final PackageSetting pkg : mPackages.values()) { + writePackageLPr(serializer, pkg); + } + + for (final PackageSetting pkg : mDisabledSysPackages.values()) { + writeDisabledSysPackageLPr(serializer, pkg); + } + + serializer.startTag(null, "preferred-activities"); + for (final PreferredActivity pa : mPreferredActivities.filterSet()) { + serializer.startTag(null, "item"); + pa.writeToXml(serializer); + serializer.endTag(null, "item"); + } + serializer.endTag(null, "preferred-activities"); + + for (final SharedUserSetting usr : mSharedUsers.values()) { + serializer.startTag(null, "shared-user"); + serializer.attribute(null, "name", usr.name); + serializer.attribute(null, "userId", + Integer.toString(usr.userId)); + usr.signatures.writeXml(serializer, "sigs", mPastSignatures); + serializer.startTag(null, "perms"); + for (String name : usr.grantedPermissions) { + serializer.startTag(null, "item"); + serializer.attribute(null, "name", name); + serializer.endTag(null, "item"); + } + serializer.endTag(null, "perms"); + serializer.endTag(null, "shared-user"); + } + + if (mPackagesToBeCleaned.size() > 0) { + for (int i=0; i 0) { + for (HashMap.Entry e : mRenamedPackages.entrySet()) { + serializer.startTag(null, "renamed-package"); + serializer.attribute(null, "new", e.getKey()); + serializer.attribute(null, "old", e.getValue()); + serializer.endTag(null, "renamed-package"); + } + } + + serializer.endTag(null, "packages"); + + serializer.endDocument(); + + str.flush(); + FileUtils.sync(fstr); + str.close(); + + // New settings successfully written, old ones are no longer + // needed. + mBackupSettingsFilename.delete(); + FileUtils.setPermissions(mSettingsFilename.toString(), + FileUtils.S_IRUSR|FileUtils.S_IWUSR + |FileUtils.S_IRGRP|FileUtils.S_IWGRP + |FileUtils.S_IROTH, + -1, -1); + + // Write package list file now, use a JournaledFile. + // + File tempFile = new File(mPackageListFilename.toString() + ".tmp"); + JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile); + + fstr = new FileOutputStream(journal.chooseForWrite()); + str = new BufferedOutputStream(fstr); + try { + StringBuilder sb = new StringBuilder(); + for (final PackageSetting pkg : mPackages.values()) { + ApplicationInfo ai = pkg.pkg.applicationInfo; + String dataPath = ai.dataDir; + boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + + // Avoid any application that has a space in its path + // or that is handled by the system. + if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID) + continue; + + // we store on each line the following information for now: + // + // pkgName - package name + // userId - application-specific user id + // debugFlag - 0 or 1 if the package is debuggable. + // dataPath - path to package's data path + // + // NOTE: We prefer not to expose all ApplicationInfo flags for now. + // + // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS + // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES: + // system/core/run-as/run-as.c + // + sb.setLength(0); + sb.append(ai.packageName); + sb.append(" "); + sb.append((int)ai.uid); + sb.append(isDebug ? " 1 " : " 0 "); + sb.append(dataPath); + sb.append("\n"); + str.write(sb.toString().getBytes()); + } + str.flush(); + FileUtils.sync(fstr); + str.close(); + journal.commit(); + } + catch (Exception e) { + journal.rollback(); + } + + FileUtils.setPermissions(mPackageListFilename.toString(), + FileUtils.S_IRUSR|FileUtils.S_IWUSR + |FileUtils.S_IRGRP|FileUtils.S_IWGRP + |FileUtils.S_IROTH, + -1, -1); + + writeStoppedLPr(); + + return; + + } catch(XmlPullParserException e) { + Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, " + + "current changes will be lost at reboot", e); + } catch(java.io.IOException e) { + Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, " + + "current changes will be lost at reboot", e); + } + // Clean up partially written files + if (mSettingsFilename.exists()) { + if (!mSettingsFilename.delete()) { + Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: " + mSettingsFilename); + } + } + //Debug.stopMethodTracing(); + } + + void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg) + throws java.io.IOException { + serializer.startTag(null, "updated-package"); + serializer.attribute(null, "name", pkg.name); + if (pkg.realName != null) { + serializer.attribute(null, "realName", pkg.realName); + } + serializer.attribute(null, "codePath", pkg.codePathString); + serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); + serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); + serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); + serializer.attribute(null, "version", String.valueOf(pkg.versionCode)); + if (!pkg.resourcePathString.equals(pkg.codePathString)) { + serializer.attribute(null, "resourcePath", pkg.resourcePathString); + } + if (pkg.nativeLibraryPathString != null) { + serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); + } + if (pkg.sharedUser == null) { + serializer.attribute(null, "userId", Integer.toString(pkg.userId)); + } else { + serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId)); + } + serializer.startTag(null, "perms"); + if (pkg.sharedUser == null) { + // If this is a shared user, the permissions will + // be written there. We still need to write an + // empty permissions list so permissionsFixed will + // be set. + for (final String name : pkg.grantedPermissions) { + BasePermission bp = mPermissions.get(name); + if (bp != null) { + // We only need to write signature or system permissions but + // this wont + // match the semantics of grantedPermissions. So write all + // permissions. + serializer.startTag(null, "item"); + serializer.attribute(null, "name", name); + serializer.endTag(null, "item"); + } + } + } + serializer.endTag(null, "perms"); + serializer.endTag(null, "updated-package"); + } + + void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg) + throws java.io.IOException { + serializer.startTag(null, "package"); + serializer.attribute(null, "name", pkg.name); + if (pkg.realName != null) { + serializer.attribute(null, "realName", pkg.realName); + } + serializer.attribute(null, "codePath", pkg.codePathString); + if (!pkg.resourcePathString.equals(pkg.codePathString)) { + serializer.attribute(null, "resourcePath", pkg.resourcePathString); + } + if (pkg.nativeLibraryPathString != null) { + serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); + } + serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags)); + serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); + serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); + serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); + serializer.attribute(null, "version", String.valueOf(pkg.versionCode)); + if (pkg.sharedUser == null) { + serializer.attribute(null, "userId", Integer.toString(pkg.userId)); + } else { + serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId)); + } + if (pkg.uidError) { + serializer.attribute(null, "uidError", "true"); + } + if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) { + serializer.attribute(null, "enabled", + pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED ? "true" : "false"); + } + if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) { + serializer.attribute(null, "installStatus", "false"); + } + if (pkg.installerPackageName != null) { + serializer.attribute(null, "installer", pkg.installerPackageName); + } + pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); + if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { + serializer.startTag(null, "perms"); + if (pkg.sharedUser == null) { + // If this is a shared user, the permissions will + // be written there. We still need to write an + // empty permissions list so permissionsFixed will + // be set. + for (final String name : pkg.grantedPermissions) { + serializer.startTag(null, "item"); + serializer.attribute(null, "name", name); + serializer.endTag(null, "item"); + } + } + serializer.endTag(null, "perms"); + } + if (pkg.disabledComponents.size() > 0) { + serializer.startTag(null, "disabled-components"); + for (final String name : pkg.disabledComponents) { + serializer.startTag(null, "item"); + serializer.attribute(null, "name", name); + serializer.endTag(null, "item"); + } + serializer.endTag(null, "disabled-components"); + } + if (pkg.enabledComponents.size() > 0) { + serializer.startTag(null, "enabled-components"); + for (final String name : pkg.enabledComponents) { + serializer.startTag(null, "item"); + serializer.attribute(null, "name", name); + serializer.endTag(null, "item"); + } + serializer.endTag(null, "enabled-components"); + } + + serializer.endTag(null, "package"); + } + + void writePermissionLPr(XmlSerializer serializer, BasePermission bp) + throws XmlPullParserException, java.io.IOException { + if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) { + serializer.startTag(null, "item"); + serializer.attribute(null, "name", bp.name); + serializer.attribute(null, "package", bp.sourcePackage); + if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) { + serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel)); + } + if (PackageManagerService.DEBUG_SETTINGS) + Log.v(PackageManagerService.TAG, "Writing perm: name=" + bp.name + " type=" + + bp.type); + if (bp.type == BasePermission.TYPE_DYNAMIC) { + final PermissionInfo pi = bp.perm != null ? bp.perm.info : bp.pendingInfo; + if (pi != null) { + serializer.attribute(null, "type", "dynamic"); + if (pi.icon != 0) { + serializer.attribute(null, "icon", Integer.toString(pi.icon)); + } + if (pi.nonLocalizedLabel != null) { + serializer.attribute(null, "label", pi.nonLocalizedLabel.toString()); + } + } + } + serializer.endTag(null, "item"); + } + } + + ArrayList getListOfIncompleteInstallPackagesLPr() { + final HashSet kList = new HashSet(mPackages.keySet()); + final Iterator its = kList.iterator(); + final ArrayList ret = new ArrayList(); + while (its.hasNext()) { + final String key = its.next(); + final PackageSetting ps = mPackages.get(key); + if (ps.getInstallStatus() == PackageSettingBase.PKG_INSTALL_INCOMPLETE) { + ret.add(ps); + } + } + return ret; + } + + boolean readLPw() { + FileInputStream str = null; + if (mBackupSettingsFilename.exists()) { + try { + str = new FileInputStream(mBackupSettingsFilename); + mReadMessages.append("Reading from backup settings file\n"); + PackageManagerService.reportSettingsProblem(Log.INFO, + "Need to read from backup settings file"); + if (mSettingsFilename.exists()) { + // If both the backup and settings file exist, we + // ignore the settings since it might have been + // corrupted. + Slog.w(PackageManagerService.TAG, "Cleaning up settings file " + + mSettingsFilename); + mSettingsFilename.delete(); + } + } catch (java.io.IOException e) { + // We'll try for the normal settings file. + } + } + + mPendingPackages.clear(); + mPastSignatures.clear(); + + try { + if (str == null) { + if (!mSettingsFilename.exists()) { + mReadMessages.append("No settings file found\n"); + PackageManagerService.reportSettingsProblem(Log.INFO, + "No settings file; creating initial state"); + return false; + } + str = new FileInputStream(mSettingsFilename); + } + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(str, null); + + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + ; + } + + if (type != XmlPullParser.START_TAG) { + mReadMessages.append("No start tag found in settings file\n"); + PackageManagerService.reportSettingsProblem(Log.WARN, + "No start tag found in package manager settings"); + Log + .wtf(PackageManagerService.TAG, + "No start tag found in package manager settings"); + return false; + } + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("package")) { + readPackageLPw(parser); + } else if (tagName.equals("permissions")) { + readPermissionsLPw(mPermissions, parser); + } else if (tagName.equals("permission-trees")) { + readPermissionsLPw(mPermissionTrees, parser); + } else if (tagName.equals("shared-user")) { + readSharedUserLPw(parser); + } else if (tagName.equals("preferred-packages")) { + // no longer used. + } else if (tagName.equals("preferred-activities")) { + readPreferredActivitiesLPw(parser); + } else if (tagName.equals("updated-package")) { + readDisabledSysPackageLPw(parser); + } else if (tagName.equals("cleaning-package")) { + String name = parser.getAttributeValue(null, "name"); + if (name != null) { + mPackagesToBeCleaned.add(name); + } + } else if (tagName.equals("renamed-package")) { + String nname = parser.getAttributeValue(null, "new"); + String oname = parser.getAttributeValue(null, "old"); + if (nname != null && oname != null) { + mRenamedPackages.put(nname, oname); + } + } else if (tagName.equals("last-platform-version")) { + mInternalSdkPlatform = mExternalSdkPlatform = 0; + try { + String internal = parser.getAttributeValue(null, "internal"); + if (internal != null) { + mInternalSdkPlatform = Integer.parseInt(internal); + } + String external = parser.getAttributeValue(null, "external"); + if (external != null) { + mExternalSdkPlatform = Integer.parseInt(external); + } + } catch (NumberFormatException e) { + } + } else { + Slog.w(PackageManagerService.TAG, "Unknown element under : " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + str.close(); + + } catch (XmlPullParserException e) { + mReadMessages.append("Error reading: " + e.toString()); + PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); + Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e); + + } catch (java.io.IOException e) { + mReadMessages.append("Error reading: " + e.toString()); + PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); + Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e); + + } + + final int N = mPendingPackages.size(); + for (int i = 0; i < N; i++) { + final PendingPackage pp = mPendingPackages.get(i); + Object idObj = getUserIdLPr(pp.sharedId); + if (idObj != null && idObj instanceof SharedUserSetting) { + PackageSetting p = getPackageLPw(pp.name, null, pp.realName, + (SharedUserSetting) idObj, pp.codePath, pp.resourcePath, + pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true); + if (p == null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unable to create application package for " + pp.name); + continue; + } + p.copyFrom(pp); + } else if (idObj != null) { + String msg = "Bad package setting: package " + pp.name + " has shared uid " + + pp.sharedId + " that is not a shared uid\n"; + mReadMessages.append(msg); + PackageManagerService.reportSettingsProblem(Log.ERROR, msg); + } else { + String msg = "Bad package setting: package " + pp.name + " has shared uid " + + pp.sharedId + " that is not defined\n"; + mReadMessages.append(msg); + PackageManagerService.reportSettingsProblem(Log.ERROR, msg); + } + } + mPendingPackages.clear(); + + readStoppedLPw(); + + mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, " + + mSharedUsers.size() + " shared uids\n"); + + return true; + } + + private int readInt(XmlPullParser parser, String ns, String name, int defValue) { + String v = parser.getAttributeValue(ns, name); + try { + if (v == null) { + return defValue; + } + return Integer.parseInt(v); + } catch (NumberFormatException e) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: attribute " + name + + " has bad integer value " + v + " at " + + parser.getPositionDescription()); + } + return defValue; + } + + private void readPermissionsLPw(HashMap out, XmlPullParser parser) + throws IOException, XmlPullParserException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + final String tagName = parser.getName(); + if (tagName.equals("item")) { + final String name = parser.getAttributeValue(null, "name"); + final String sourcePackage = parser.getAttributeValue(null, "package"); + final String ptype = parser.getAttributeValue(null, "type"); + if (name != null && sourcePackage != null) { + final boolean dynamic = "dynamic".equals(ptype); + final BasePermission bp = new BasePermission(name, sourcePackage, + dynamic ? BasePermission.TYPE_DYNAMIC : BasePermission.TYPE_NORMAL); + bp.protectionLevel = readInt(parser, null, "protection", + PermissionInfo.PROTECTION_NORMAL); + if (dynamic) { + PermissionInfo pi = new PermissionInfo(); + pi.packageName = sourcePackage.intern(); + pi.name = name.intern(); + pi.icon = readInt(parser, null, "icon", 0); + pi.nonLocalizedLabel = parser.getAttributeValue(null, "label"); + pi.protectionLevel = bp.protectionLevel; + bp.pendingInfo = pi; + } + out.put(bp.name, bp); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: permissions has" + " no name at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element reading permissions: " + parser.getName() + " at " + + parser.getPositionDescription()); + } + XmlUtils.skipCurrentTag(parser); + } + } + + private void readDisabledSysPackageLPw(XmlPullParser parser) throws XmlPullParserException, + IOException { + String name = parser.getAttributeValue(null, "name"); + String realName = parser.getAttributeValue(null, "realName"); + String codePathStr = parser.getAttributeValue(null, "codePath"); + String resourcePathStr = parser.getAttributeValue(null, "resourcePath"); + String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); + if (resourcePathStr == null) { + resourcePathStr = codePathStr; + } + String version = parser.getAttributeValue(null, "version"); + int versionCode = 0; + if (version != null) { + try { + versionCode = Integer.parseInt(version); + } catch (NumberFormatException e) { + } + } + + int pkgFlags = 0; + pkgFlags |= ApplicationInfo.FLAG_SYSTEM; + PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr), + new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags); + String timeStampStr = parser.getAttributeValue(null, "ft"); + if (timeStampStr != null) { + try { + long timeStamp = Long.parseLong(timeStampStr, 16); + ps.setTimeStamp(timeStamp); + } catch (NumberFormatException e) { + } + } else { + timeStampStr = parser.getAttributeValue(null, "ts"); + if (timeStampStr != null) { + try { + long timeStamp = Long.parseLong(timeStampStr); + ps.setTimeStamp(timeStamp); + } catch (NumberFormatException e) { + } + } + } + timeStampStr = parser.getAttributeValue(null, "it"); + if (timeStampStr != null) { + try { + ps.firstInstallTime = Long.parseLong(timeStampStr, 16); + } catch (NumberFormatException e) { + } + } + timeStampStr = parser.getAttributeValue(null, "ut"); + if (timeStampStr != null) { + try { + ps.lastUpdateTime = Long.parseLong(timeStampStr, 16); + } catch (NumberFormatException e) { + } + } + String idStr = parser.getAttributeValue(null, "userId"); + ps.userId = idStr != null ? Integer.parseInt(idStr) : 0; + if (ps.userId <= 0) { + String sharedIdStr = parser.getAttributeValue(null, "sharedUserId"); + ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; + } + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("perms")) { + readGrantedPermissionsLPw(parser, ps.grantedPermissions); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + mDisabledSysPackages.put(name, ps); + } + + private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException { + String name = null; + String realName = null; + String idStr = null; + String sharedIdStr = null; + String codePathStr = null; + String resourcePathStr = null; + String nativeLibraryPathStr = null; + String systemStr = null; + String installerPackageName = null; + String uidError = null; + int pkgFlags = 0; + long timeStamp = 0; + long firstInstallTime = 0; + long lastUpdateTime = 0; + PackageSettingBase packageSetting = null; + String version = null; + int versionCode = 0; + try { + name = parser.getAttributeValue(null, "name"); + realName = parser.getAttributeValue(null, "realName"); + idStr = parser.getAttributeValue(null, "userId"); + uidError = parser.getAttributeValue(null, "uidError"); + sharedIdStr = parser.getAttributeValue(null, "sharedUserId"); + codePathStr = parser.getAttributeValue(null, "codePath"); + resourcePathStr = parser.getAttributeValue(null, "resourcePath"); + nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); + version = parser.getAttributeValue(null, "version"); + if (version != null) { + try { + versionCode = Integer.parseInt(version); + } catch (NumberFormatException e) { + } + } + installerPackageName = parser.getAttributeValue(null, "installer"); + + systemStr = parser.getAttributeValue(null, "flags"); + if (systemStr != null) { + try { + pkgFlags = Integer.parseInt(systemStr); + } catch (NumberFormatException e) { + } + } else { + // For backward compatibility + systemStr = parser.getAttributeValue(null, "system"); + if (systemStr != null) { + pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM + : 0; + } else { + // Old settings that don't specify system... just treat + // them as system, good enough. + pkgFlags |= ApplicationInfo.FLAG_SYSTEM; + } + } + String timeStampStr = parser.getAttributeValue(null, "ft"); + if (timeStampStr != null) { + try { + timeStamp = Long.parseLong(timeStampStr, 16); + } catch (NumberFormatException e) { + } + } else { + timeStampStr = parser.getAttributeValue(null, "ts"); + if (timeStampStr != null) { + try { + timeStamp = Long.parseLong(timeStampStr); + } catch (NumberFormatException e) { + } + } + } + timeStampStr = parser.getAttributeValue(null, "it"); + if (timeStampStr != null) { + try { + firstInstallTime = Long.parseLong(timeStampStr, 16); + } catch (NumberFormatException e) { + } + } + timeStampStr = parser.getAttributeValue(null, "ut"); + if (timeStampStr != null) { + try { + lastUpdateTime = Long.parseLong(timeStampStr, 16); + } catch (NumberFormatException e) { + } + } + if (PackageManagerService.DEBUG_SETTINGS) + Log.v(PackageManagerService.TAG, "Reading package: " + name + " userId=" + idStr + + " sharedUserId=" + sharedIdStr); + int userId = idStr != null ? Integer.parseInt(idStr) : 0; + if (resourcePathStr == null) { + resourcePathStr = codePathStr; + } + if (realName != null) { + realName = realName.intern(); + } + if (name == null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has no name at " + + parser.getPositionDescription()); + } else if (codePathStr == null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has no codePath at " + + parser.getPositionDescription()); + } else if (userId > 0) { + packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr), + new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode, + pkgFlags); + if (PackageManagerService.DEBUG_SETTINGS) + Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" + + userId + " pkg=" + packageSetting); + if (packageSetting == null) { + PackageManagerService.reportSettingsProblem(Log.ERROR, "Failure adding uid " + + userId + " while parsing settings at " + + parser.getPositionDescription()); + } else { + packageSetting.setTimeStamp(timeStamp); + packageSetting.firstInstallTime = firstInstallTime; + packageSetting.lastUpdateTime = lastUpdateTime; + } + } else if (sharedIdStr != null) { + userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; + if (userId > 0) { + packageSetting = new PendingPackage(name.intern(), realName, new File( + codePathStr), new File(resourcePathStr), nativeLibraryPathStr, userId, + versionCode, pkgFlags); + packageSetting.setTimeStamp(timeStamp); + packageSetting.firstInstallTime = firstInstallTime; + packageSetting.lastUpdateTime = lastUpdateTime; + mPendingPackages.add((PendingPackage) packageSetting); + if (PackageManagerService.DEBUG_SETTINGS) + Log.i(PackageManagerService.TAG, "Reading package " + name + + ": sharedUserId=" + userId + " pkg=" + packageSetting); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: package " + name + + " has bad sharedId " + sharedIdStr + " at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: package " + name + " has bad userId " + + idStr + " at " + parser.getPositionDescription()); + } + } catch (NumberFormatException e) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: package " + name + " has bad userId " + + idStr + " at " + parser.getPositionDescription()); + } + if (packageSetting != null) { + packageSetting.uidError = "true".equals(uidError); + packageSetting.installerPackageName = installerPackageName; + packageSetting.nativeLibraryPathString = nativeLibraryPathStr; + final String enabledStr = parser.getAttributeValue(null, "enabled"); + if (enabledStr != null) { + if (enabledStr.equalsIgnoreCase("true")) { + packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED; + } else if (enabledStr.equalsIgnoreCase("false")) { + packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED; + } else if (enabledStr.equalsIgnoreCase("default")) { + packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT; + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: package " + name + + " has bad enabled value: " + idStr + " at " + + parser.getPositionDescription()); + } + } else { + packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT; + } + final String installStatusStr = parser.getAttributeValue(null, "installStatus"); + if (installStatusStr != null) { + if (installStatusStr.equalsIgnoreCase("false")) { + packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_INCOMPLETE; + } else { + packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_COMPLETE; + } + } + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("disabled-components")) { + readDisabledComponentsLPw(packageSetting, parser); + } else if (tagName.equals("enabled-components")) { + readEnabledComponentsLPw(packageSetting, parser); + } else if (tagName.equals("sigs")) { + packageSetting.signatures.readXml(parser, mPastSignatures); + } else if (tagName.equals("perms")) { + readGrantedPermissionsLPw(parser, packageSetting.grantedPermissions); + packageSetting.permissionsFixed = true; + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + } else { + XmlUtils.skipCurrentTag(parser); + } + } + + private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser) + throws IOException, XmlPullParserException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("item")) { + String name = parser.getAttributeValue(null, "name"); + if (name != null) { + packageSetting.disabledComponents.add(name.intern()); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has" + + " no name at " + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + } + XmlUtils.skipCurrentTag(parser); + } + } + + private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser) + throws IOException, XmlPullParserException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("item")) { + String name = parser.getAttributeValue(null, "name"); + if (name != null) { + packageSetting.enabledComponents.add(name.intern()); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has" + + " no name at " + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + } + XmlUtils.skipCurrentTag(parser); + } + } + + private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException, IOException { + String name = null; + String idStr = null; + int pkgFlags = 0; + SharedUserSetting su = null; + try { + name = parser.getAttributeValue(null, "name"); + idStr = parser.getAttributeValue(null, "userId"); + int userId = idStr != null ? Integer.parseInt(idStr) : 0; + if ("true".equals(parser.getAttributeValue(null, "system"))) { + pkgFlags |= ApplicationInfo.FLAG_SYSTEM; + } + if (name == null) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has no name at " + + parser.getPositionDescription()); + } else if (userId == 0) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: shared-user " + name + + " has bad userId " + idStr + " at " + + parser.getPositionDescription()); + } else { + if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags)) == null) { + PackageManagerService + .reportSettingsProblem(Log.ERROR, "Occurred while parsing settings at " + + parser.getPositionDescription()); + } + } + } catch (NumberFormatException e) { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: package " + name + " has bad userId " + + idStr + " at " + parser.getPositionDescription()); + } + ; + + if (su != null) { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("sigs")) { + su.signatures.readXml(parser, mPastSignatures); + } else if (tagName.equals("perms")) { + readGrantedPermissionsLPw(parser, su.grantedPermissions); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + } else { + XmlUtils.skipCurrentTag(parser); + } + } + + private void readGrantedPermissionsLPw(XmlPullParser parser, HashSet outPerms) + throws IOException, XmlPullParserException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("item")) { + String name = parser.getAttributeValue(null, "name"); + if (name != null) { + outPerms.add(name.intern()); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: has" + " no name at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + } + XmlUtils.skipCurrentTag(parser); + } + } + + private void readPreferredActivitiesLPw(XmlPullParser parser) throws XmlPullParserException, + IOException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("item")) { + PreferredActivity pa = new PreferredActivity(parser); + if (pa.mPref.getParseError() == null) { + mPreferredActivities.addFilter(pa); + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Error in package manager settings: " + + pa.mPref.getParseError() + " at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + } + + // Returns -1 if we could not find an available UserId to assign + private int newUserIdLPw(Object obj) { + // Let's be stupidly inefficient for now... + final int N = mUserIds.size(); + for (int i = 0; i < N; i++) { + if (mUserIds.get(i) == null) { + mUserIds.set(i, obj); + return PackageManagerService.FIRST_APPLICATION_UID + i; + } + } + + // None left? + if (N >= PackageManagerService.MAX_APPLICATION_UIDS) { + return -1; + } + + mUserIds.add(obj); + return PackageManagerService.FIRST_APPLICATION_UID + N; + } + + public PackageSetting getDisabledSystemPkgLPr(String name) { + PackageSetting ps = mDisabledSysPackages.get(name); + return ps; + } + + boolean isEnabledLPr(ComponentInfo componentInfo, int flags) { + if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { + return true; + } + final PackageSetting packageSettings = mPackages.get(componentInfo.packageName); + if (PackageManagerService.DEBUG_SETTINGS) { + Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = " + componentInfo.packageName + + " componentName = " + componentInfo.name); + Log.v(PackageManagerService.TAG, "enabledComponents: " + + Arrays.toString(packageSettings.enabledComponents.toArray())); + Log.v(PackageManagerService.TAG, "disabledComponents: " + + Arrays.toString(packageSettings.disabledComponents.toArray())); + } + if (packageSettings == null) { + return false; + } + if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED + || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled + && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) { + return false; + } + if (packageSettings.enabledComponents.contains(componentInfo.name)) { + return true; + } + if (packageSettings.disabledComponents.contains(componentInfo.name)) { + return false; + } + return componentInfo.enabled; + } + + String getInstallerPackageNameLPr(String packageName) { + final PackageSetting pkg = mPackages.get(packageName); + if (pkg == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + return pkg.installerPackageName; + } + + int getApplicationEnabledSettingLPr(String packageName) { + final PackageSetting pkg = mPackages.get(packageName); + if (pkg == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + return pkg.enabled; + } + + int getComponentEnabledSettingLPr(ComponentName componentName) { + final String packageName = componentName.getPackageName(); + final PackageSetting pkg = mPackages.get(packageName); + if (pkg == null) { + throw new IllegalArgumentException("Unknown component: " + componentName); + } + final String classNameStr = componentName.getClassName(); + return pkg.getCurrentEnabledStateLPr(classNameStr); + } + + boolean setPackageStoppedStateLPw(String packageName, boolean stopped, + boolean allowedByPermission, int uid) { + final PackageSetting pkgSetting = mPackages.get(packageName); + if (pkgSetting == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + if (!allowedByPermission && (uid != pkgSetting.userId)) { + throw new SecurityException( + "Permission Denial: attempt to change stopped state from pid=" + + Binder.getCallingPid() + + ", uid=" + uid + ", package uid=" + pkgSetting.userId); + } + if (DEBUG_STOPPED) { + if (stopped) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(TAG, "Stopping package " + packageName, e); + } + } + if (pkgSetting.stopped != stopped) { + pkgSetting.stopped = stopped; + pkgSetting.pkg.mSetStopped = stopped; + if (pkgSetting.notLaunched) { + if (pkgSetting.installerPackageName != null) { + PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, + pkgSetting.name, null, + pkgSetting.installerPackageName, null); + } + pkgSetting.notLaunched = false; + } + return true; + } + return false; + } + + void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState) { + final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + final Date date = new Date(); + boolean printedSomething = false; + for (final PackageSetting ps : mPackages.values()) { + if (packageName != null && !packageName.equals(ps.realName) + && !packageName.equals(ps.name)) { + continue; + } + + if (packageName != null) { + dumpState.setSharedUser(ps.sharedUser); + } + + if (!printedSomething) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + pw.println("Packages:"); + printedSomething = true; + } + pw.print(" Package ["); + pw.print(ps.realName != null ? ps.realName : ps.name); + pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(ps))); + pw.println("):"); + + if (ps.realName != null) { + pw.print(" compat name="); + pw.println(ps.name); + } + + pw.print(" userId="); pw.print(ps.userId); + pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids)); + pw.print(" sharedUser="); pw.println(ps.sharedUser); + pw.print(" pkg="); pw.println(ps.pkg); + pw.print(" codePath="); pw.println(ps.codePathString); + pw.print(" resourcePath="); pw.println(ps.resourcePathString); + pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString); + pw.print(" versionCode="); pw.println(ps.versionCode); + if (ps.pkg != null) { + pw.print(" versionName="); pw.println(ps.pkg.mVersionName); + pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); + pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion); + if (ps.pkg.mOperationPending) { + pw.println(" mOperationPending=true"); + } + pw.print(" supportsScreens=["); + boolean first = true; + if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { + if (!first) + pw.print(", "); + first = false; + pw.print("small"); + } + if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { + if (!first) + pw.print(", "); + first = false; + pw.print("medium"); + } + if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + if (!first) + pw.print(", "); + first = false; + pw.print("large"); + } + if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { + if (!first) + pw.print(", "); + first = false; + pw.print("xlarge"); + } + if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { + if (!first) + pw.print(", "); + first = false; + pw.print("resizeable"); + } + if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { + if (!first) + pw.print(", "); + first = false; + pw.print("anyDensity"); + } + } + pw.println("]"); + pw.print(" timeStamp="); + date.setTime(ps.timeStamp); + pw.println(sdf.format(date)); + pw.print(" firstInstallTime="); + date.setTime(ps.firstInstallTime); + pw.println(sdf.format(date)); + pw.print(" lastUpdateTime="); + date.setTime(ps.lastUpdateTime); + pw.println(sdf.format(date)); + if (ps.installerPackageName != null) { + pw.print(" installerPackageName="); pw.println(ps.installerPackageName); + } + pw.print(" signatures="); pw.println(ps.signatures); + pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed); + pw.print(" haveGids="); pw.println(ps.haveGids); + pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags)); + pw.print(" installStatus="); pw.print(ps.installStatus); + pw.print(" stopped="); pw.print(ps.stopped); + pw.print(" enabled="); pw.println(ps.enabled); + if (ps.disabledComponents.size() > 0) { + pw.println(" disabledComponents:"); + for (String s : ps.disabledComponents) { + pw.print(" "); pw.println(s); + } + } + if (ps.enabledComponents.size() > 0) { + pw.println(" enabledComponents:"); + for (String s : ps.enabledComponents) { + pw.print(" "); pw.println(s); + } + } + if (ps.grantedPermissions.size() > 0) { + pw.println(" grantedPermissions:"); + for (String s : ps.grantedPermissions) { + pw.print(" "); pw.println(s); + } + } + } + + printedSomething = false; + if (mRenamedPackages.size() > 0) { + for (final HashMap.Entry e : mRenamedPackages.entrySet()) { + if (packageName != null && !packageName.equals(e.getKey()) + && !packageName.equals(e.getValue())) { + continue; + } + if (!printedSomething) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + pw.println("Renamed packages:"); + printedSomething = true; + } + pw.print(" "); + pw.print(e.getKey()); + pw.print(" -> "); + pw.println(e.getValue()); + } + } + + printedSomething = false; + if (mDisabledSysPackages.size() > 0) { + for (final PackageSetting ps : mDisabledSysPackages.values()) { + if (packageName != null && !packageName.equals(ps.realName) + && !packageName.equals(ps.name)) { + continue; + } + if (!printedSomething) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + pw.println("Hidden system packages:"); + printedSomething = true; + } + pw.print(" Package ["); + pw.print(ps.realName != null ? ps.realName : ps.name); + pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(ps))); + pw.println("):"); + if (ps.realName != null) { + pw.print(" compat name="); + pw.println(ps.name); + } + pw.print(" userId="); + pw.println(ps.userId); + pw.print(" sharedUser="); + pw.println(ps.sharedUser); + pw.print(" codePath="); + pw.println(ps.codePathString); + pw.print(" resourcePath="); + pw.println(ps.resourcePathString); + } + } + } + + void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) { + boolean printedSomething = false; + for (BasePermission p : mPermissions.values()) { + if (packageName != null && !packageName.equals(p.sourcePackage)) { + continue; + } + if (!printedSomething) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + pw.println("Permissions:"); + printedSomething = true; + } + pw.print(" Permission ["); pw.print(p.name); pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(p))); + pw.println("):"); + pw.print(" sourcePackage="); pw.println(p.sourcePackage); + pw.print(" uid="); pw.print(p.uid); + pw.print(" gids="); pw.print(PackageManagerService.arrayToString(p.gids)); + pw.print(" type="); pw.print(p.type); + pw.print(" prot="); pw.println(p.protectionLevel); + if (p.packageSetting != null) { + pw.print(" packageSetting="); pw.println(p.packageSetting); + } + if (p.perm != null) { + pw.print(" perm="); pw.println(p.perm); + } + } + } + + void dumpSharedUsersLPr(PrintWriter pw, String packageName, DumpState dumpState) { + boolean printedSomething = false; + for (SharedUserSetting su : mSharedUsers.values()) { + if (packageName != null && su != dumpState.getSharedUser()) { + continue; + } + if (!printedSomething) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + pw.println("Shared users:"); + printedSomething = true; + } + pw.print(" SharedUser ["); + pw.print(su.name); + pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(su))); + pw.println("):"); + pw.print(" userId="); + pw.print(su.userId); + pw.print(" gids="); + pw.println(PackageManagerService.arrayToString(su.gids)); + pw.println(" grantedPermissions:"); + for (String s : su.grantedPermissions) { + pw.print(" "); + pw.println(s); + } + } + } + + void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) { + pw.println("Settings parse messages:"); + pw.print(mReadMessages.toString()); + } +} \ No newline at end of file diff --git a/services/java/com/android/server/pm/SharedUserSetting.java b/services/java/com/android/server/pm/SharedUserSetting.java new file mode 100644 index 0000000000000..76826eab2f07a --- /dev/null +++ b/services/java/com/android/server/pm/SharedUserSetting.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import java.util.HashSet; + +/** + * Settings data for a particular shared user ID we know about. + */ +final class SharedUserSetting extends GrantedPermissions { + final String name; + + int userId; + + final HashSet packages = new HashSet(); + + final PackageSignatures signatures = new PackageSignatures(); + + SharedUserSetting(String _name, int _pkgFlags) { + super(_pkgFlags); + name = _name; + } + + @Override + public String toString() { + return "SharedUserSetting{" + Integer.toHexString(System.identityHashCode(this)) + " " + + name + "/" + userId + "}"; + } +}