am 465e9967: Merge "Consolidated processing of package boardcasts in AM service." into lmp-mr1-dev

* commit '465e996776d916d8d1b62c539142827bd96a42bc':
  Consolidated processing of package boardcasts in AM service.
This commit is contained in:
Wale Ogunwale
2014-11-17 19:30:16 +00:00
committed by Android Git Automerger

View File

@@ -61,7 +61,6 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
@@ -1832,99 +1831,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
};
/**
* Monitor for package changes and update our internal state.
*/
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
public void onPackageRemoved(String packageName, int uid) {
// Remove all tasks with activities in the specified package from the list of recent tasks
final int eventUserId = getChangingUserId();
synchronized (ActivityManagerService.this) {
for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
TaskRecord tr = mRecentTasks.get(i);
if (tr.userId != eventUserId) continue;
ComponentName cn = tr.intent.getComponent();
if (cn != null && cn.getPackageName().equals(packageName)) {
// If the package name matches, remove the task
removeTaskByIdLocked(tr.taskId, true);
}
}
}
}
@Override
public boolean onPackageChanged(String packageName, int uid, String[] components) {
onPackageModified(packageName);
return true;
}
@Override
public void onPackageModified(String packageName) {
final int eventUserId = getChangingUserId();
final IPackageManager pm = AppGlobals.getPackageManager();
final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
new ArrayList<Pair<Intent, Integer>>();
final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
final ArrayList<Integer> tasksToRemove = new ArrayList<Integer>();
// Copy the list of recent tasks so that we don't hold onto the lock on
// ActivityManagerService for long periods while checking if components exist.
synchronized (ActivityManagerService.this) {
for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
TaskRecord tr = mRecentTasks.get(i);
if (tr.userId != eventUserId) continue;
recentTaskIntents.add(new Pair<Intent, Integer>(tr.intent, tr.taskId));
}
}
// Check the recent tasks and filter out all tasks with components that no longer exist.
for (int i = recentTaskIntents.size() - 1; i >= 0; i--) {
Pair<Intent, Integer> p = recentTaskIntents.get(i);
ComponentName cn = p.first.getComponent();
if (cn != null && cn.getPackageName().equals(packageName)) {
if (componentsKnownToExist.contains(cn)) {
// If we know that the component still exists in the package, then skip
continue;
}
try {
ActivityInfo info = pm.getActivityInfo(cn, 0, eventUserId);
if (info != null) {
componentsKnownToExist.add(cn);
} else {
tasksToRemove.add(p.second);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to query activity info for component: " + cn, e);
}
}
}
// Prune all the tasks with removed components from the list of recent tasks
synchronized (ActivityManagerService.this) {
for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
removeTaskByIdLocked(tasksToRemove.get(i), false);
}
}
}
@Override
public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
// Force stop the specified packages
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (packages != null) {
for (String pkg : packages) {
synchronized (ActivityManagerService.this) {
if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
userId, "finished booting")) {
return true;
}
}
}
}
return false;
}
};
public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
@@ -6172,8 +6078,26 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
// Register receivers to handle package update events
mPackageMonitor.register(mContext, Looper.getMainLooper(), UserHandle.ALL, false);
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
pkgFilter.addDataScheme("package");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
if (pkgs != null) {
for (String pkg : pkgs) {
synchronized (ActivityManagerService.this) {
if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
0, "finished booting")) {
setResultCode(Activity.RESULT_OK);
return;
}
}
}
}
}
}, pkgFilter);
// Let system services know.
mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -8407,6 +8331,47 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
private void removeTasksByPackageNameLocked(String packageName, int userId) {
// Remove all tasks with activities in the specified package from the list of recent tasks
for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
TaskRecord tr = mRecentTasks.get(i);
if (tr.userId != userId) continue;
ComponentName cn = tr.intent.getComponent();
if (cn != null && cn.getPackageName().equals(packageName)) {
// If the package name matches, remove the task.
removeTaskByIdLocked(tr.taskId, true);
}
}
}
private void removeTasksByRemovedPackageComponentsLocked(String packageName, int userId) {
final IPackageManager pm = AppGlobals.getPackageManager();
final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
TaskRecord tr = mRecentTasks.get(i);
if (tr.userId != userId) continue;
ComponentName cn = tr.intent.getComponent();
if (cn != null && cn.getPackageName().equals(packageName)) {
// Skip if component still exists in the package.
if (componentsKnownToExist.contains(cn)) continue;
try {
ActivityInfo info = pm.getActivityInfo(cn, 0, userId);
if (info != null) {
componentsKnownToExist.add(cn);
} else {
removeTaskByIdLocked(tr.taskId, false);
}
} catch (RemoteException e) {
Log.e(TAG, "Activity info query failed. component=" + cn, e);
}
}
}
}
/**
* Removes the task with the specified task id.
*
@@ -15674,126 +15639,133 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
// Handle special intents: if this broadcast is from the package
// manager about a package being removed, we need to remove all of
// its activities from the history stack.
final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
intent.getAction());
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
|| Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
|| Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())
|| uidRemoved) {
if (checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
callingPid, callingUid, -1, true)
== PackageManager.PERMISSION_GRANTED) {
if (uidRemoved) {
final Bundle intentExtras = intent.getExtras();
final int uid = intentExtras != null
? intentExtras.getInt(Intent.EXTRA_UID) : -1;
if (uid >= 0) {
BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
synchronized (bs) {
bs.removeUidStatsLocked(uid);
}
mAppOpsService.uidRemoved(uid);
final String action = intent.getAction();
if (action != null) {
switch (action) {
case Intent.ACTION_UID_REMOVED:
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
// Handle special intents: if this broadcast is from the package
// manager about a package being removed, we need to remove all of
// its activities from the history stack.
if (checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
callingPid, callingUid, -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} else {
// If resources are unavailable just force stop all
// those packages and flush the attribute cache as well.
if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && (list.length > 0)) {
for (String pkg : list) {
forceStopPackageLocked(pkg, -1, false, true, true, false, false, userId,
"storage unmount");
switch (action) {
case Intent.ACTION_UID_REMOVED:
final Bundle intentExtras = intent.getExtras();
final int uid = intentExtras != null
? intentExtras.getInt(Intent.EXTRA_UID) : -1;
if (uid >= 0) {
BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
synchronized (bs) {
bs.removeUidStatsLocked(uid);
}
mAppOpsService.uidRemoved(uid);
}
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
// If resources are unavailable just force stop all those packages
// and flush the attribute cache as well.
String list[] =
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && list.length > 0) {
for (int i = 0; i < list.length; i++) {
forceStopPackageLocked(list[i], -1, false, true, true,
false, false, userId, "storage unmount");
}
cleanupRecentTasksLocked(UserHandle.USER_ALL);
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,
userId);
}
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
cleanupRecentTasksLocked(UserHandle.USER_ALL);
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId);
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(
intent.getAction())) {
cleanupRecentTasksLocked(UserHandle.USER_ALL);
} else {
Uri data = intent.getData();
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(
intent.getAction());
boolean fullUninstall = removed &&
!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)), false, true, true,
false, fullUninstall, userId,
removed ? "pkg removed" : "pkg changed");
}
if (removed) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
new String[] {ssp}, userId);
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
mAppOpsService.packageRemoved(
intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
break;
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
Uri data = intent.getData();
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
boolean fullUninstall = removed &&
!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
false, true, true, false, fullUninstall, userId,
removed ? "pkg removed" : "pkg changed");
}
if (removed) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
new String[] {ssp}, userId);
if (fullUninstall) {
mAppOpsService.packageRemoved(
intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
removeTasksByPackageNameLocked(ssp, userId);
}
} else {
removeTasksByRemovedPackageComponentsLocked(ssp, userId);
}
}
break;
}
break;
case Intent.ACTION_PACKAGE_ADDED:
// Special case for adding a package: by default turn on compatibility mode.
Uri data = intent.getData();
String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
final boolean replacing =
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
if (replacing) {
removeTasksByRemovedPackageComponentsLocked(ssp, userId);
}
}
}
} else {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Slog.w(TAG, msg);
throw new SecurityException(msg);
break;
case Intent.ACTION_TIMEZONE_CHANGED:
// If this is the time zone changed action, queue up a message that will reset
// the timezone of all currently running processes. This message will get
// queued up before the broadcast happens.
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
break;
case Intent.ACTION_TIME_CHANGED:
// If the user set the time, let all running processes know.
final int is24Hour =
intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1
: 0;
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
stats.noteCurrentTimeChangedLocked();
}
break;
case Intent.ACTION_CLEAR_DNS_CACHE:
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
break;
case Proxy.PROXY_CHANGE_ACTION:
ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
break;
}
// Special case for adding a package: by default turn on compatibility
// mode.
} else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Uri data = intent.getData();
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
mCompatModePackages.handlePackageAddedLocked(ssp,
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
}
}
/*
* If this is the time zone changed action, queue up a message that will reset the timezone
* of all currently running processes. This message will get queued up before the broadcast
* happens.
*/
if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
}
/*
* If the user set the time, let all running processes know.
*/
if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
final int is24Hour = intent.getBooleanExtra(
Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
stats.noteCurrentTimeChangedLocked();
}
}
if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
}
if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
}
// Add to the sticky list if requested.