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:
@@ -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=""android.intent.extra.changed_component_name_list""
|
||||||
|
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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user