use of com.android.internal.os.BatteryStatsImpl in project cornerstone by Onskreen.
the class ActivityManagerService method updateOomAdjLocked.
private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
app.hiddenAdj = hiddenAdj;
if (app.thread == null) {
return false;
}
final boolean wasKeeping = app.keeping;
boolean success = true;
computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
if (app.curRawAdj != app.setRawAdj) {
if (wasKeeping && !app.keeping) {
// This app is no longer something we want to keep. Note
// its current wake lock time to later know to kill it if
// it is not behaving well.
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
app.lastWakeTime = stats.getProcessWakeTime(app.info.uid, app.pid, SystemClock.elapsedRealtime());
}
app.lastCpuTime = app.curCpuTime;
}
app.setRawAdj = app.curRawAdj;
}
if (app.curAdj != app.setAdj) {
if (Process.setOomAdj(app.pid, app.curAdj)) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ)
Slog.v(TAG, "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
} else {
success = false;
Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
}
}
if (app.setSchedGroup != app.curSchedGroup) {
app.setSchedGroup = app.curSchedGroup;
if (DEBUG_SWITCH || DEBUG_OOM_ADJ)
Slog.v(TAG, "Setting process group of " + app.processName + " to " + app.curSchedGroup);
if (app.waitingToKill != null && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
EventLog.writeEvent(EventLogTags.AM_KILL, app.pid, app.processName, app.setAdj, app.waitingToKill);
app.killedBackground = true;
Process.killProcessQuiet(app.pid);
success = false;
} else {
if (true) {
long oldId = Binder.clearCallingIdentity();
try {
Process.setProcessGroup(app.pid, app.curSchedGroup);
} catch (Exception e) {
Slog.w(TAG, "Failed setting process group of " + app.pid + " to " + app.curSchedGroup);
e.printStackTrace();
} finally {
Binder.restoreCallingIdentity(oldId);
}
} else {
if (app.thread != null) {
try {
app.thread.setSchedulingGroup(app.curSchedGroup);
} catch (RemoteException e) {
}
}
}
}
}
return success;
}
use of com.android.internal.os.BatteryStatsImpl in project cornerstone by Onskreen.
the class ActivityManagerService method updateCpuStatsNow.
void updateCpuStatsNow() {
synchronized (mProcessStatsThread) {
mProcessStatsMutexFree.set(false);
final long now = SystemClock.uptimeMillis();
boolean haveNewCpuStats = false;
if (MONITOR_CPU_USAGE && mLastCpuTime.get() < (now - MONITOR_CPU_MIN_TIME)) {
mLastCpuTime.set(now);
haveNewCpuStats = true;
mProcessStats.update();
// Slog the cpu usage if the property is set.
if ("true".equals(SystemProperties.get("events.cpu"))) {
int user = mProcessStats.getLastUserTime();
int system = mProcessStats.getLastSystemTime();
int iowait = mProcessStats.getLastIoWaitTime();
int irq = mProcessStats.getLastIrqTime();
int softIrq = mProcessStats.getLastSoftIrqTime();
int idle = mProcessStats.getLastIdleTime();
int total = user + system + iowait + irq + softIrq + idle;
if (total == 0)
total = 1;
EventLog.writeEvent(EventLogTags.CPU, ((user + system + iowait + irq + softIrq) * 100) / total, (user * 100) / total, (system * 100) / total, (iowait * 100) / total, (irq * 100) / total, (softIrq * 100) / total);
}
}
long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
synchronized (bstats) {
synchronized (mPidsSelfLocked) {
if (haveNewCpuStats) {
if (mOnBattery) {
int perc = bstats.startAddingCpuLocked();
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessStats.countStats();
for (int i = 0; i < N; i++) {
ProcessStats.Stats st = mProcessStats.getStats(i);
if (!st.working) {
continue;
}
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime * perc) / 100;
int otherSTime = (st.rel_stime * perc) / 100;
totalUTime += otherUTime;
totalSTime += otherSTime;
if (pr != null) {
BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
ps.addCpuTimeLocked(st.rel_utime - otherUTime, st.rel_stime - otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
pr.curCpuTime += (st.rel_utime + st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps = bstats.getProcessStatsLocked(st.name, st.pid);
if (ps != null) {
ps.addCpuTimeLocked(st.rel_utime - otherUTime, st.rel_stime - otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
}
}
}
bstats.finishAddingCpuLocked(perc, totalUTime, totalSTime, cpuSpeedTimes);
}
}
}
if (mLastWriteTime < (now - BATTERY_STATS_TIME)) {
mLastWriteTime = now;
mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
}
}
}
}
use of com.android.internal.os.BatteryStatsImpl in project cornerstone by Onskreen.
the class ActivityManagerService method dumpProcessOomList.
private static final boolean dumpProcessOomList(PrintWriter pw, ActivityManagerService service, List<ProcessRecord> origList, String prefix, String normalLabel, String persistentLabel, boolean inclDetails, String dumpPackage) {
ArrayList<Pair<ProcessRecord, Integer>> list = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
for (int i = 0; i < origList.size(); i++) {
ProcessRecord r = origList.get(i);
if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
continue;
}
list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
}
if (list.size() <= 0) {
return false;
}
Comparator<Pair<ProcessRecord, Integer>> comparator = new Comparator<Pair<ProcessRecord, Integer>>() {
@Override
public int compare(Pair<ProcessRecord, Integer> object1, Pair<ProcessRecord, Integer> object2) {
if (object1.first.setAdj != object2.first.setAdj) {
return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
}
if (object1.second.intValue() != object2.second.intValue()) {
return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
}
return 0;
}
};
Collections.sort(list, comparator);
final long curRealtime = SystemClock.elapsedRealtime();
final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
final long curUptime = SystemClock.uptimeMillis();
final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
for (int i = list.size() - 1; i >= 0; i--) {
ProcessRecord r = list.get(i).first;
String oomAdj;
if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
} else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
} else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
} else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
} else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
} else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
} else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
} else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
} else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
} else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
} else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
} else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
} else {
oomAdj = Integer.toString(r.setAdj);
}
String schedGroup;
switch(r.setSchedGroup) {
case Process.THREAD_GROUP_BG_NONINTERACTIVE:
schedGroup = "B";
break;
case Process.THREAD_GROUP_DEFAULT:
schedGroup = "F";
break;
default:
schedGroup = Integer.toString(r.setSchedGroup);
break;
}
String foreground;
if (r.foregroundActivities) {
foreground = "A";
} else if (r.foregroundServices) {
foreground = "S";
} else {
foreground = " ";
}
pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)", prefix, (r.persistent ? persistentLabel : normalLabel), (origList.size() - 1) - list.get(i).second, oomAdj, schedGroup, foreground, r.trimMemoryLevel, r.toShortString(), r.adjType));
if (r.adjSource != null || r.adjTarget != null) {
pw.print(prefix);
pw.print(" ");
if (r.adjTarget instanceof ComponentName) {
pw.print(((ComponentName) r.adjTarget).flattenToShortString());
} else if (r.adjTarget != null) {
pw.print(r.adjTarget.toString());
} else {
pw.print("{null}");
}
pw.print("<=");
if (r.adjSource instanceof ProcessRecord) {
pw.print("Proc{");
pw.print(((ProcessRecord) r.adjSource).toShortString());
pw.println("}");
} else if (r.adjSource != null) {
pw.println(r.adjSource.toString());
} else {
pw.println("{null}");
}
}
if (inclDetails) {
pw.print(prefix);
pw.print(" ");
pw.print("oom: max=");
pw.print(r.maxAdj);
pw.print(" hidden=");
pw.print(r.hiddenAdj);
pw.print(" curRaw=");
pw.print(r.curRawAdj);
pw.print(" setRaw=");
pw.print(r.setRawAdj);
pw.print(" cur=");
pw.print(r.curAdj);
pw.print(" set=");
pw.println(r.setAdj);
pw.print(prefix);
pw.print(" ");
pw.print("keeping=");
pw.print(r.keeping);
pw.print(" hidden=");
pw.print(r.hidden);
pw.print(" empty=");
pw.print(r.empty);
pw.print(" hasAboveClient=");
pw.println(r.hasAboveClient);
if (!r.keeping) {
if (r.lastWakeTime != 0) {
long wtime;
BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
wtime = stats.getProcessWakeTime(r.info.uid, r.pid, curRealtime);
}
long timeUsed = wtime - r.lastWakeTime;
pw.print(prefix);
pw.print(" ");
pw.print("keep awake over ");
TimeUtils.formatDuration(realtimeSince, pw);
pw.print(" used ");
TimeUtils.formatDuration(timeUsed, pw);
pw.print(" (");
pw.print((timeUsed * 100) / realtimeSince);
pw.println("%)");
}
if (r.lastCpuTime != 0) {
long timeUsed = r.curCpuTime - r.lastCpuTime;
pw.print(prefix);
pw.print(" ");
pw.print("run cpu over ");
TimeUtils.formatDuration(uptimeSince, pw);
pw.print(" used ");
TimeUtils.formatDuration(timeUsed, pw);
pw.print(" (");
pw.print((timeUsed * 100) / uptimeSince);
pw.println("%)");
}
}
}
}
return true;
}
use of com.android.internal.os.BatteryStatsImpl in project cornerstone by Onskreen.
the class ActivityManagerService method bindBackupAgent.
// =========================================================
// BACKUP AND RESTORE
// =========================================================
// Cause the target app to be launched if necessary and its backup agent
// instantiated. The backup agent will invoke backupAgentCreated() on the
// activity manager to announce its creation.
public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
if (DEBUG_BACKUP)
Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
synchronized (this) {
// !!! TODO: currently no check here that we're already bound
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
}
// Backup agent is now in use, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(app.packageName, false, UserId.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package " + app.packageName + ": " + e);
}
BackupRecord r = new BackupRecord(ss, app, backupMode);
ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) ? new ComponentName(app.packageName, app.backupAgentName) : new ComponentName("android", "FullBackupAgent");
// startProcessLocked() returns existing proc's record if it's already running
ProcessRecord proc = startProcessLocked(app.processName, app, false, 0, "backup", hostingName, false, false);
if (proc == null) {
Slog.e(TAG, "Unable to start backup agent process " + r);
return false;
}
r.app = proc;
mBackupTarget = r;
mBackupAppName = app.packageName;
// Try not to kill the process during backup
updateOomAdjLocked(proc);
// If it is not yet live, this will be done when it attaches to the framework.
if (proc.thread != null) {
if (DEBUG_BACKUP)
Slog.v(TAG, "Agent proc already running: " + proc);
try {
proc.thread.scheduleCreateBackupAgent(app, compatibilityInfoForPackageLocked(app), backupMode);
} catch (RemoteException e) {
// Will time out on the backup manager side
}
} else {
if (DEBUG_BACKUP)
Slog.v(TAG, "Agent proc not running, waiting for attach");
}
// Invariants: at this point, the target app process exists and the application
// is either already running or in the process of coming up. mBackupTarget and
// mBackupAppName describe the app, so that when it binds back to the AM we
// know that it's scheduled for a backup-agent operation.
}
return true;
}
use of com.android.internal.os.BatteryStatsImpl in project cornerstone by Onskreen.
the class ActivityManagerService method broadcastIntentLocked.
private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
if (DEBUG_BROADCAST_LIGHT)
Slog.v(TAG, (sticky ? "Broadcast sticky: " : "Broadcast: ") + intent + " ordered=" + ordered + " userid=" + userId);
if ((resultTo != null) && !ordered) {
Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
}
// 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()) || 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);
}
}
} else {
// 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, userId);
}
sendPackageBroadcastLocked(IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
}
} else {
Uri data = intent.getData();
String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
forceStopPackageLocked(ssp, intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false, userId);
}
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, new String[] { ssp });
}
}
}
}
} 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);
}
// 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 (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
}
if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
ProxyProperties proxy = intent.getParcelableExtra("proxy");
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
}
/*
* Prevent non-system code (defined here to be non-persistent
* processes) from sending protected broadcasts.
*/
if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID || callingUid == Process.SHELL_UID || callingUid == 0) {
// Always okay.
} else if (callerApp == null || !callerApp.persistent) {
try {
if (AppGlobals.getPackageManager().isProtectedBroadcast(intent.getAction())) {
String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from pid=" + callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
return ActivityManager.BROADCAST_SUCCESS;
}
}
// Add to the sticky list if requested.
if (sticky) {
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, callingPid, callingUid) != PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid=" + callingPid + ", uid=" + callingUid + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
if (requiredPermission != null) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent + " and enforce permission " + requiredPermission);
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
if (intent.getComponent() != null) {
throw new SecurityException("Sticky broadcasts can't target a specific component");
}
ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
if (list == null) {
list = new ArrayList<Intent>();
mStickyBroadcasts.put(intent.getAction(), list);
}
int N = list.size();
int i;
for (i = 0; i < N; i++) {
if (intent.filterEquals(list.get(i))) {
// This sticky already exists, replace it.
list.set(i, new Intent(intent));
break;
}
}
if (i >= N) {
list.add(new Intent(intent));
}
}
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
try {
if (intent.getComponent() != null) {
// Broadcast is going to one specific receiver class...
ActivityInfo ai = AppGlobals.getPackageManager().getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS, userId);
if (ai != null) {
receivers = new ArrayList();
ResolveInfo ri = new ResolveInfo();
if (isSingleton(ai.processName, ai.applicationInfo)) {
ri.activityInfo = getActivityInfoForUser(ai, 0);
} else {
ri.activityInfo = getActivityInfoForUser(ai, userId);
}
receivers.add(ri);
}
} else {
// Need to resolve the intent to interested receivers...
if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
receivers = AppGlobals.getPackageManager().queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, userId);
}
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId);
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
final boolean replacePending = (intent.getFlags() & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
if (DEBUG_BROADCAST)
Slog.v(TAG, "Enqueing broadcast: " + intent.getAction() + " replacePending=" + replacePending);
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, registeredReceivers, resultTo, resultCode, resultData, map, ordered, sticky, false);
if (DEBUG_BROADCAST)
Slog.v(TAG, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
// Merge into one list.
int ir = 0;
if (receivers != null) {
// A special case for PACKAGE_ADDED: do not allow the package
// being added to see this broadcast. This prevents them from
// using this as a back door to get run as soon as they are
// installed. Maybe in the future we want to have a special install
// broadcast or such for apps, but we'd like to deliberately make
// this decision.
String[] skipPackages = null;
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Uri data = intent.getData();
if (data != null) {
String pkgName = data.getSchemeSpecificPart();
if (pkgName != null) {
skipPackages = new String[] { pkgName };
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
if (skipPackages != null && (skipPackages.length > 0)) {
for (String skipPackage : skipPackages) {
if (skipPackage != null) {
int NT = receivers.size();
for (int it = 0; it < NT; it++) {
ResolveInfo curt = (ResolveInfo) receivers.get(it);
if (curt.activityInfo.packageName.equals(skipPackage)) {
receivers.remove(it);
it--;
NT--;
}
}
}
}
}
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null;
BroadcastFilter curr = null;
while (it < NT && ir < NR) {
if (curt == null) {
curt = (ResolveInfo) receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
if (curr.getPriority() >= curt.priority) {
// Insert this broadcast record into the final list.
receivers.add(it, curr);
ir++;
curr = null;
it++;
NT++;
} else {
// Skip to the next ResolveInfo in the final list.
it++;
curt = null;
}
}
}
while (ir < NR) {
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
if ((receivers != null && receivers.size() > 0) || resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false);
if (DEBUG_BROADCAST)
Slog.v(TAG, "Enqueueing ordered broadcast " + r + ": prev had " + queue.mOrderedBroadcasts.size());
if (DEBUG_BROADCAST) {
int seq = r.intent.getIntExtra("seq", -1);
Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
}
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
Aggregations