am c5dc6872: am 360d710e: Merge change I580de484 into eclair

Merge commit 'c5dc6872dac40f87b6b8261c3cd5260a52325aba' into eclair-mr2-plus-aosp

* commit 'c5dc6872dac40f87b6b8261c3cd5260a52325aba':
  Fix issue #2256270: Package manager sends bad broadcasts when components change
This commit is contained in:
Dianne Hackborn
2009-11-11 20:28:27 -08:00
committed by Android Git Automerger
3 changed files with 70 additions and 28 deletions

View File

@@ -36147,6 +36147,17 @@
visibility="public" visibility="public"
> >
</field> </field>
<field name="EXTRA_CHANGED_COMPONENT_NAME_LIST"
type="java.lang.String"
transient="false"
volatile="false"
value="&quot;android.intent.extra.changed_component_name_list&quot;"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="EXTRA_DATA_REMOVED" <field name="EXTRA_DATA_REMOVED"
type="java.lang.String" type="java.lang.String"
transient="false" transient="false"

View File

@@ -1275,12 +1275,15 @@ public class Intent implements Parcelable {
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
/** /**
* Broadcast Action: An existing application package has been changed (e.g. a component has been * Broadcast Action: An existing application package has been changed (e.g.
* enabled or disabled. The data contains the name of the package. * a component has been enabled or disabled). The data contains the name of
* the package.
* <ul> * <ul>
* <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
* <li> {@link #EXTRA_CHANGED_COMPONENT_NAME} containing the class name of the changed component. * <li> {@link #EXTRA_CHANGED_COMPONENT_NAME_LIST} containing the class name
* <li> {@link #EXTRA_DONT_KILL_APP} containing boolean field to override the default action of restarting the application. * of the changed components.
* <li> {@link #EXTRA_DONT_KILL_APP} containing boolean field to override the
* default action of restarting the application.
* </ul> * </ul>
* *
* <p class="note">This is a protected intent that can only be sent * <p class="note">This is a protected intent that can only be sent
@@ -2101,13 +2104,19 @@ public class Intent implements Parcelable {
"android.intent.extra.remote_intent_token"; "android.intent.extra.remote_intent_token";
/** /**
* Used as an int extra field in {@link android.content.Intent#ACTION_PACKAGE_CHANGED} * @Deprecated See {@link #EXTRA_CHANGED_COMPONENT_NAME_LIST}; this field
* intent to supply the name of the component that changed. * will contain only the first name in the list.
*
*/ */
public static final String EXTRA_CHANGED_COMPONENT_NAME = public static final String EXTRA_CHANGED_COMPONENT_NAME =
"android.intent.extra.changed_component_name"; "android.intent.extra.changed_component_name";
/**
* This field is part of {@link android.content.Intent#ACTION_PACKAGE_CHANGED}
* and contains a string array of all of the components that have changed.
*/
public static final String EXTRA_CHANGED_COMPONENT_NAME_LIST =
"android.intent.extra.changed_component_name_list";
/** /**
* @hide * @hide
* Magic extra system code can use when binding, to give a label for * Magic extra system code can use when binding, to give a label for

View File

@@ -277,7 +277,8 @@ class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package mPlatformPackage; PackageParser.Package mPlatformPackage;
// Set of pending broadcasts for aggregating enable/disable of components. // Set of pending broadcasts for aggregating enable/disable of components.
final HashMap<String, String> mPendingBroadcasts = new HashMap<String, String>(); final HashMap<String, ArrayList<String>> mPendingBroadcasts
= new HashMap<String, ArrayList<String>>();
static final int SEND_PENDING_BROADCAST = 1; static final int SEND_PENDING_BROADCAST = 1;
// Delay time in millisecs // Delay time in millisecs
static final int BROADCAST_DELAY = 10 * 1000; static final int BROADCAST_DELAY = 10 * 1000;
@@ -289,30 +290,40 @@ class PackageManagerService extends IPackageManager.Stub {
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
case SEND_PENDING_BROADCAST : { case SEND_PENDING_BROADCAST : {
String packages[];
ArrayList components[];
int size = 0; int size = 0;
String broadcastList[];
HashMap<String, String> tmpMap;
int uids[]; int uids[];
synchronized (mPackages) { synchronized (mPackages) {
if (mPendingBroadcasts == null) {
return;
}
size = mPendingBroadcasts.size(); size = mPendingBroadcasts.size();
if (size <= 0) { if (size <= 0) {
// Nothing to be done. Just return // Nothing to be done. Just return
return; return;
} }
broadcastList = new String[size]; packages = new String[size];
mPendingBroadcasts.keySet().toArray(broadcastList); components = new ArrayList[size];
tmpMap = new HashMap<String, String>(mPendingBroadcasts);
uids = new int[size]; uids = new int[size];
for (int i = 0; i < size; i++) { Iterator<HashMap.Entry<String, ArrayList<String>>>
PackageSetting ps = mSettings.mPackages.get(mPendingBroadcasts.get(broadcastList[i])); it = mPendingBroadcasts.entrySet().iterator();
int i = 0;
while (it.hasNext() && i < size) {
HashMap.Entry<String, ArrayList<String>> ent = it.next();
packages[i] = ent.getKey();
components[i] = ent.getValue();
PackageSetting ps = mSettings.mPackages.get(ent.getKey());
uids[i] = (ps != null) ? ps.userId : -1; uids[i] = (ps != null) ? ps.userId : -1;
i++;
} }
size = i;
mPendingBroadcasts.clear(); mPendingBroadcasts.clear();
} }
// Send broadcasts // Send broadcasts
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
String className = broadcastList[i]; sendPackageChangedBroadcast(packages[i], true,
sendPackageChangedBroadcast(className, true, tmpMap.get(className), uids[i]); (ArrayList<String>)components[i], uids[i]);
} }
break; break;
} }
@@ -5023,8 +5034,9 @@ class PackageManagerService extends IPackageManager.Stub {
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
boolean sendNow = false; boolean sendNow = false;
boolean isApp = (className == null); boolean isApp = (className == null);
String key = isApp ? packageName : className; String componentName = isApp ? packageName : className;
int packageUid = -1; int packageUid = -1;
ArrayList<String> components;
synchronized (mPackages) { synchronized (mPackages) {
pkgSetting = mSettings.mPackages.get(packageName); pkgSetting = mSettings.mPackages.get(packageName);
if (pkgSetting == null) { if (pkgSetting == null) {
@@ -5064,17 +5076,22 @@ class PackageManagerService extends IPackageManager.Stub {
} }
mSettings.writeLP(); mSettings.writeLP();
packageUid = pkgSetting.userId; packageUid = pkgSetting.userId;
components = mPendingBroadcasts.get(packageName);
boolean newPackage = components == null;
if (newPackage) {
components = new ArrayList<String>();
}
if (!components.contains(componentName)) {
components.add(componentName);
}
if ((flags&PackageManager.DONT_KILL_APP) == 0) { if ((flags&PackageManager.DONT_KILL_APP) == 0) {
sendNow = true; sendNow = true;
// Purge entry from pending broadcast list if another one exists already // Purge entry from pending broadcast list if another one exists already
// since we are sending one right away. // since we are sending one right away.
if (mPendingBroadcasts.get(key) != null) { mPendingBroadcasts.remove(packageName);
mPendingBroadcasts.remove(key);
// Can ignore empty list since its handled in the handler anyway
}
} else { } else {
if (mPendingBroadcasts.get(key) == null) { if (newPackage) {
mPendingBroadcasts.put(key, packageName); mPendingBroadcasts.put(packageName, components);
} }
if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
// Schedule a message // Schedule a message
@@ -5087,7 +5104,7 @@ class PackageManagerService extends IPackageManager.Stub {
try { try {
if (sendNow) { if (sendNow) {
sendPackageChangedBroadcast(packageName, sendPackageChangedBroadcast(packageName,
(flags&PackageManager.DONT_KILL_APP) != 0, key, packageUid); (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
} }
} finally { } finally {
Binder.restoreCallingIdentity(callingId); Binder.restoreCallingIdentity(callingId);
@@ -5095,9 +5112,14 @@ class PackageManagerService extends IPackageManager.Stub {
} }
private void sendPackageChangedBroadcast(String packageName, private void sendPackageChangedBroadcast(String packageName,
boolean killFlag, String componentName, int packageUid) { boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Bundle extras = new Bundle(2); if (false) Log.v(TAG, "Sending package changed: package=" + packageName
extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentName); + " components=" + componentNames);
Bundle extras = new Bundle(4);
extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
String nameList[] = new String[componentNames.size()];
componentNames.toArray(nameList);
extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag); extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
extras.putInt(Intent.EXTRA_UID, packageUid); extras.putInt(Intent.EXTRA_UID, packageUid);
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras); sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);