Merge changes Ia7add63e,Ic7571dae

* changes:
  Split dump and annotate users of mPackages lock
  Split PackageManagerService into subclasses
This commit is contained in:
Kenny Root
2011-03-25 14:41:34 -07:00
committed by Android (Google) Code Review
14 changed files with 4024 additions and 3552 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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
+ "}";
}
}

View File

@@ -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<String> grantedPermissions = new HashSet<String>();
int[] gids;
GrantedPermissions(int pkgFlags) {
setFlags(pkgFlags);
}
@SuppressWarnings("unchecked")
GrantedPermissions(GrantedPermissions base) {
pkgFlags = base.pkgFlags;
grantedPermissions = (HashSet<String>) 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);
}
}

View File

@@ -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");

View File

@@ -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 + "}";
}
}

View File

@@ -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<String> disabledComponents = new HashSet<String>(0);
/* Explicitly enabled components */
HashSet<String> enabledComponents = new HashSet<String>(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<String>) base.disabledComponents.clone();
enabledComponents = (HashSet<String>) 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;
}
}
}

View File

@@ -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<Signature> pastSignatures) throws IOException {
if (mSignatures == null) {
return;
}
serializer.startTag(null, tagName);
serializer.attribute(null, "count",
Integer.toString(mSignatures.length));
for (int i=0; i<mSignatures.length; i++) {
serializer.startTag(null, "cert");
final Signature sig = mSignatures[i];
final int sigHash = sig.hashCode();
final int numPast = pastSignatures.size();
int j;
for (j=0; j<numPast; j++) {
Signature pastSig = pastSignatures.get(j);
if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
serializer.attribute(null, "index", Integer.toString(j));
break;
}
}
if (j >= 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<Signature> pastSignatures)
throws IOException, XmlPullParserException {
String countStr = parser.getAttributeValue(null, "count");
if (countStr == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <signatures> 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: <cert> "
+ "index " + index + " is not defined at "
+ parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> "
+ "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: <cert> "
+ "index " + index + " is not a number at "
+ parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> has"
+ " no index at " + parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: too "
+ "many <cert> tags, expected " + count
+ " at " + parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Unknown element under <cert>: "
+ 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<sigs.length; i++) {
mSignatures[i] = sigs[i];
}
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer(128);
buf.append("PackageSignatures{");
buf.append(Integer.toHexString(System.identityHashCode(this)));
buf.append(" [");
if (mSignatures != null) {
for (int i=0; i<mSignatures.length; i++) {
if (i > 0) buf.append(", ");
buf.append(Integer.toHexString(
System.identityHashCode(mSignatures[i])));
}
}
buf.append("]}");
return buf.toString();
}
}

View File

@@ -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;
}
}

View File

@@ -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 <preferred-activities>: " + parser.getName());
XmlUtils.skipCurrentTag(parser);
}
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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<PackageSetting> packages = new HashSet<PackageSetting>();
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 + "}";
}
}