* commit '9210bc85545f31973c957b5179e6a82d05f473c6': Implement #10744011: Serialize running of background services
This commit is contained in:
@@ -20,12 +20,12 @@ import java.io.FileDescriptor;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import com.android.internal.app.ProcessStats;
|
import com.android.internal.app.ProcessStats;
|
||||||
import com.android.internal.os.BatteryStatsImpl;
|
import com.android.internal.os.BatteryStatsImpl;
|
||||||
import com.android.internal.os.TransferPipe;
|
import com.android.internal.os.TransferPipe;
|
||||||
@@ -54,7 +54,6 @@ import android.os.RemoteException;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.EventLog;
|
import android.util.EventLog;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.TimeUtils;
|
import android.util.TimeUtils;
|
||||||
@@ -62,6 +61,8 @@ import android.util.TimeUtils;
|
|||||||
public final class ActiveServices {
|
public final class ActiveServices {
|
||||||
static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
|
static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
|
||||||
static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
|
static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
|
||||||
|
static final boolean DEBUG_DELAYED_SERVICE = ActivityManagerService.DEBUG_SERVICE;
|
||||||
|
static final boolean DEBUG_DELAYED_STATS = DEBUG_DELAYED_SERVICE;
|
||||||
static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
|
static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
|
||||||
static final String TAG = ActivityManagerService.TAG;
|
static final String TAG = ActivityManagerService.TAG;
|
||||||
static final String TAG_MU = ActivityManagerService.TAG_MU;
|
static final String TAG_MU = ActivityManagerService.TAG_MU;
|
||||||
@@ -94,16 +95,24 @@ public final class ActiveServices {
|
|||||||
// LRU background list.
|
// LRU background list.
|
||||||
static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
|
static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
|
||||||
|
|
||||||
|
// How long we wait for a background started service to stop itself before
|
||||||
|
// allowing the next pending start to run.
|
||||||
|
static final int BG_START_TIMEOUT = 15*1000;
|
||||||
|
|
||||||
final ActivityManagerService mAm;
|
final ActivityManagerService mAm;
|
||||||
|
|
||||||
final ServiceMap mServiceMap = new ServiceMap();
|
// Maximum number of services that we allow to start in the background
|
||||||
|
// at the same time.
|
||||||
|
final int mMaxStartingBackground;
|
||||||
|
|
||||||
|
final SparseArray<ServiceMap> mServiceMap = new SparseArray<ServiceMap>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All currently bound service connections. Keys are the IBinder of
|
* All currently bound service connections. Keys are the IBinder of
|
||||||
* the client's IServiceConnection.
|
* the client's IServiceConnection.
|
||||||
*/
|
*/
|
||||||
final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
|
final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
|
||||||
= new HashMap<IBinder, ArrayList<ConnectionRecord>>();
|
= new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of services that we have been asked to start,
|
* List of services that we have been asked to start,
|
||||||
@@ -126,97 +135,127 @@ public final class ActiveServices {
|
|||||||
final ArrayList<ServiceRecord> mStoppingServices
|
final ArrayList<ServiceRecord> mStoppingServices
|
||||||
= new ArrayList<ServiceRecord>();
|
= new ArrayList<ServiceRecord>();
|
||||||
|
|
||||||
static class ServiceMap {
|
static final class DelayingProcess extends ArrayList<ServiceRecord> {
|
||||||
|
long timeoout;
|
||||||
|
}
|
||||||
|
|
||||||
private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
|
/**
|
||||||
= new SparseArray<HashMap<ComponentName, ServiceRecord>>();
|
* Information about services for a single user.
|
||||||
private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
|
*/
|
||||||
mServicesByIntentPerUser = new SparseArray<
|
class ServiceMap extends Handler {
|
||||||
HashMap<Intent.FilterComparison, ServiceRecord>>();
|
final ArrayMap<ComponentName, ServiceRecord> mServicesByName
|
||||||
|
= new ArrayMap<ComponentName, ServiceRecord>();
|
||||||
|
final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent
|
||||||
|
= new ArrayMap<Intent.FilterComparison, ServiceRecord>();
|
||||||
|
|
||||||
ServiceRecord getServiceByName(ComponentName name, int callingUser) {
|
final ArrayList<ServiceRecord> mDelayedStartList
|
||||||
// TODO: Deal with global services
|
= new ArrayList<ServiceRecord>();
|
||||||
if (DEBUG_MU)
|
/* XXX eventually I'd like to have this based on processes instead of services.
|
||||||
Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
|
* That is, if we try to start two services in a row both running in the same
|
||||||
return getServices(callingUser).get(name);
|
* process, this should be one entry in mStartingBackground for that one process
|
||||||
}
|
* that remains until all services in it are done.
|
||||||
|
final ArrayMap<ProcessRecord, DelayingProcess> mStartingBackgroundMap
|
||||||
|
= new ArrayMap<ProcessRecord, DelayingProcess>();
|
||||||
|
final ArrayList<DelayingProcess> mStartingProcessList
|
||||||
|
= new ArrayList<DelayingProcess>();
|
||||||
|
*/
|
||||||
|
|
||||||
ServiceRecord getServiceByName(ComponentName name) {
|
final ArrayList<ServiceRecord> mStartingBackground
|
||||||
return getServiceByName(name, -1);
|
= new ArrayList<ServiceRecord>();
|
||||||
}
|
|
||||||
|
|
||||||
ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
|
static final int MSG_BG_START_TIMEOUT = 1;
|
||||||
// TODO: Deal with global services
|
|
||||||
if (DEBUG_MU)
|
|
||||||
Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
|
|
||||||
return getServicesByIntent(callingUser).get(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
|
@Override
|
||||||
return getServiceByIntent(filter, -1);
|
public void handleMessage(Message msg) {
|
||||||
}
|
switch (msg.what) {
|
||||||
|
case MSG_BG_START_TIMEOUT: {
|
||||||
void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
|
synchronized (mAm) {
|
||||||
// TODO: Deal with global services
|
rescheduleDelayedStarts();
|
||||||
getServices(callingUser).put(name, value);
|
}
|
||||||
}
|
} break;
|
||||||
|
|
||||||
void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
|
|
||||||
ServiceRecord value) {
|
|
||||||
// TODO: Deal with global services
|
|
||||||
getServicesByIntent(callingUser).put(filter, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeServiceByName(ComponentName name, int callingUser) {
|
|
||||||
// TODO: Deal with global services
|
|
||||||
ServiceRecord removed = getServices(callingUser).remove(name);
|
|
||||||
if (DEBUG_MU)
|
|
||||||
Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
|
|
||||||
+ " removed=" + removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
|
|
||||||
// TODO: Deal with global services
|
|
||||||
ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
|
|
||||||
if (DEBUG_MU)
|
|
||||||
Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
|
|
||||||
+ " removed=" + removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<ServiceRecord> getAllServices(int callingUser) {
|
|
||||||
// TODO: Deal with global services
|
|
||||||
return getServices(callingUser).values();
|
|
||||||
}
|
|
||||||
|
|
||||||
private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
|
|
||||||
HashMap<ComponentName, ServiceRecord> map = mServicesByNamePerUser.get(callingUser);
|
|
||||||
if (map == null) {
|
|
||||||
map = new HashMap<ComponentName, ServiceRecord>();
|
|
||||||
mServicesByNamePerUser.put(callingUser, map);
|
|
||||||
}
|
}
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
|
void ensureNotStartingBackground(ServiceRecord r) {
|
||||||
int callingUser) {
|
if (mStartingBackground.remove(r)) {
|
||||||
HashMap<Intent.FilterComparison, ServiceRecord> map
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "No longer background starting: " + r);
|
||||||
= mServicesByIntentPerUser.get(callingUser);
|
rescheduleDelayedStarts();
|
||||||
if (map == null) {
|
}
|
||||||
map = new HashMap<Intent.FilterComparison, ServiceRecord>();
|
if (mPendingServices.remove(r)) {
|
||||||
mServicesByIntentPerUser.put(callingUser, map);
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "No longer pending start: " + r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rescheduleDelayedStarts() {
|
||||||
|
removeMessages(MSG_BG_START_TIMEOUT);
|
||||||
|
final long now = SystemClock.uptimeMillis();
|
||||||
|
for (int i=0, N=mStartingBackground.size(); i<N; i++) {
|
||||||
|
ServiceRecord r = mStartingBackground.get(i);
|
||||||
|
if (r.startingBgTimeout <= now) {
|
||||||
|
Slog.i(TAG, "Waited long enough for: " + r);
|
||||||
|
mStartingBackground.remove(i);
|
||||||
|
N--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (mDelayedStartList.size() > 0
|
||||||
|
&& mStartingBackground.size() < mMaxStartingBackground) {
|
||||||
|
ServiceRecord r = mDelayedStartList.remove(0);
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "REM FR DELAY LIST (exec next): " + r);
|
||||||
|
if (r.pendingStarts.size() <= 0) {
|
||||||
|
Slog.w(TAG, "**** NO PENDING STARTS! " + r + " startReq=" + r.startRequested
|
||||||
|
+ " delayedStop=" + r.delayedStop);
|
||||||
|
}
|
||||||
|
if (DEBUG_DELAYED_SERVICE) {
|
||||||
|
if (mDelayedStartList.size() > 0) {
|
||||||
|
Slog.v(TAG, "Remaining delayed list:");
|
||||||
|
for (int i=0; i<mDelayedStartList.size(); i++) {
|
||||||
|
Slog.v(TAG, " #" + i + ": " + mDelayedStartList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.delayed = false;
|
||||||
|
startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true);
|
||||||
|
}
|
||||||
|
if (mStartingBackground.size() > 0) {
|
||||||
|
ServiceRecord next = mStartingBackground.get(0);
|
||||||
|
long when = next.startingBgTimeout > now ? next.startingBgTimeout : now;
|
||||||
|
if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Top bg start is " + next
|
||||||
|
+ ", can delay others up to " + when);
|
||||||
|
Message msg = obtainMessage(MSG_BG_START_TIMEOUT);
|
||||||
|
sendMessageAtTime(msg, when);
|
||||||
}
|
}
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActiveServices(ActivityManagerService service) {
|
public ActiveServices(ActivityManagerService service) {
|
||||||
mAm = service;
|
mAm = service;
|
||||||
|
mMaxStartingBackground = ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceRecord getServiceByName(ComponentName name, int callingUser) {
|
||||||
|
// TODO: Deal with global services
|
||||||
|
if (DEBUG_MU)
|
||||||
|
Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
|
||||||
|
return getServiceMap(callingUser).mServicesByName.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServiceMap getServiceMap(int callingUser) {
|
||||||
|
ServiceMap smap = mServiceMap.get(callingUser);
|
||||||
|
if (smap == null) {
|
||||||
|
smap = new ServiceMap();
|
||||||
|
mServiceMap.put(callingUser, smap);
|
||||||
|
}
|
||||||
|
return smap;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayMap<ComponentName, ServiceRecord> getServices(int callingUser) {
|
||||||
|
return getServiceMap(callingUser).mServicesByName;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentName startServiceLocked(IApplicationThread caller,
|
ComponentName startServiceLocked(IApplicationThread caller,
|
||||||
Intent service, String resolvedType,
|
Intent service, String resolvedType,
|
||||||
int callingPid, int callingUid, int userId) {
|
int callingPid, int callingUid, int userId) {
|
||||||
if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "startService: " + service
|
||||||
+ " type=" + resolvedType + " args=" + service.getExtras());
|
+ " type=" + resolvedType + " args=" + service.getExtras());
|
||||||
|
|
||||||
final boolean callerFg;
|
final boolean callerFg;
|
||||||
@@ -252,13 +291,67 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
r.lastActivity = SystemClock.uptimeMillis();
|
r.lastActivity = SystemClock.uptimeMillis();
|
||||||
r.startRequested = true;
|
r.startRequested = true;
|
||||||
|
r.delayedStop = false;
|
||||||
|
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
|
||||||
|
service, neededGrants));
|
||||||
|
|
||||||
|
final ServiceMap smap = getServiceMap(r.userId);
|
||||||
|
boolean addToStarting = false;
|
||||||
|
if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {
|
||||||
|
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid);
|
||||||
|
if (proc == null || proc.curProcState >= ActivityManager.PROCESS_STATE_RECEIVER) {
|
||||||
|
// If this is not coming from a foreground caller, then we may want
|
||||||
|
// to delay the start if there are already other background services
|
||||||
|
// that are starting. This is to avoid process start spam when lots
|
||||||
|
// of applications are all handling things like connectivity broadcasts.
|
||||||
|
if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Potential start delay of " + r + " in "
|
||||||
|
+ proc);
|
||||||
|
if (r.delayed) {
|
||||||
|
// This service is already scheduled for a delayed start; just leave
|
||||||
|
// it still waiting.
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Continuing to delay: " + r);
|
||||||
|
return r.name;
|
||||||
|
}
|
||||||
|
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
|
||||||
|
// Something else is starting, delay!
|
||||||
|
Slog.i(TAG, "Delaying start of: " + r);
|
||||||
|
smap.mDelayedStartList.add(r);
|
||||||
|
r.delayed = true;
|
||||||
|
return r.name;
|
||||||
|
}
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Not delaying: " + r);
|
||||||
|
addToStarting = true;
|
||||||
|
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
|
||||||
|
// We slightly loosen when we will enqueue this new service as a background
|
||||||
|
// starting service we are waiting for, to also include processes that are
|
||||||
|
// currently running other services.
|
||||||
|
addToStarting = true;
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Not delaying, but counting as bg: " + r);
|
||||||
|
} else if (DEBUG_DELAYED_STATS) {
|
||||||
|
Slog.v(TAG, "Not potential delay (state=" + proc.curProcState
|
||||||
|
+ " " + proc.makeAdjReason() + "): " + r);
|
||||||
|
}
|
||||||
|
} else if (DEBUG_DELAYED_STATS) {
|
||||||
|
if (callerFg) {
|
||||||
|
Slog.v(TAG, "Not potential delay (callerFg=" + callerFg + " uid="
|
||||||
|
+ callingUid + " pid=" + callingPid + "): " + r);
|
||||||
|
} else if (r.app != null) {
|
||||||
|
Slog.v(TAG, "Not potential delay (cur app=" + r.app + "): " + r);
|
||||||
|
} else {
|
||||||
|
Slog.v(TAG, "Not potential delay (user " + r.userId + " not started): " + r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
|
||||||
|
ServiceRecord r, boolean callerFg, boolean addToStarting) {
|
||||||
ProcessStats.ServiceState stracker = r.getTracker();
|
ProcessStats.ServiceState stracker = r.getTracker();
|
||||||
if (stracker != null) {
|
if (stracker != null) {
|
||||||
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
|
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
|
||||||
}
|
}
|
||||||
r.callStart = false;
|
r.callStart = false;
|
||||||
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
|
|
||||||
service, neededGrants));
|
|
||||||
synchronized (r.stats.getBatteryStats()) {
|
synchronized (r.stats.getBatteryStats()) {
|
||||||
r.stats.startRunningLocked();
|
r.stats.startRunningLocked();
|
||||||
}
|
}
|
||||||
@@ -266,10 +359,37 @@ public final class ActiveServices {
|
|||||||
if (error != null) {
|
if (error != null) {
|
||||||
return new ComponentName("!!", error);
|
return new ComponentName("!!", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r.startRequested && addToStarting) {
|
||||||
|
boolean first = smap.mStartingBackground.size() == 0;
|
||||||
|
smap.mStartingBackground.add(r);
|
||||||
|
r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
|
||||||
|
if (DEBUG_DELAYED_SERVICE) {
|
||||||
|
RuntimeException here = new RuntimeException("here");
|
||||||
|
here.fillInStackTrace();
|
||||||
|
Slog.v(TAG, "Starting background (first=" + first + "): " + r, here);
|
||||||
|
} else if (DEBUG_DELAYED_STATS) {
|
||||||
|
Slog.v(TAG, "Starting background (first=" + first + "): " + r);
|
||||||
|
}
|
||||||
|
if (first) {
|
||||||
|
smap.rescheduleDelayedStarts();
|
||||||
|
}
|
||||||
|
} else if (callerFg) {
|
||||||
|
smap.ensureNotStartingBackground(r);
|
||||||
|
}
|
||||||
|
|
||||||
return r.name;
|
return r.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopServiceLocked(ServiceRecord service) {
|
private void stopServiceLocked(ServiceRecord service) {
|
||||||
|
if (service.delayed) {
|
||||||
|
// If service isn't actually running, but is is being held in the
|
||||||
|
// delayed list, then we need to keep it started but note that it
|
||||||
|
// should be stopped once no longer delayed.
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Delaying stop of pending: " + service);
|
||||||
|
service.delayedStop = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (service.stats.getBatteryStats()) {
|
synchronized (service.stats.getBatteryStats()) {
|
||||||
service.stats.stopRunningLocked();
|
service.stats.stopRunningLocked();
|
||||||
}
|
}
|
||||||
@@ -409,6 +529,7 @@ public final class ActiveServices {
|
|||||||
if (r.app != null) {
|
if (r.app != null) {
|
||||||
updateServiceForegroundLocked(r.app, true);
|
updateServiceForegroundLocked(r.app, true);
|
||||||
}
|
}
|
||||||
|
getServiceMap(r.userId).ensureNotStartingBackground(r);
|
||||||
} else {
|
} else {
|
||||||
if (r.isForeground) {
|
if (r.isForeground) {
|
||||||
r.isForeground = false;
|
r.isForeground = false;
|
||||||
@@ -591,6 +712,9 @@ public final class ActiveServices {
|
|||||||
} else if (!b.intent.requested) {
|
} else if (!b.intent.requested) {
|
||||||
requestServiceBindingLocked(s, b.intent, callerFg, false);
|
requestServiceBindingLocked(s, b.intent, callerFg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getServiceMap(s.userId).ensureNotStartingBackground(s);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(origId);
|
Binder.restoreCallingIdentity(origId);
|
||||||
}
|
}
|
||||||
@@ -713,7 +837,7 @@ public final class ActiveServices {
|
|||||||
|
|
||||||
private final ServiceRecord findServiceLocked(ComponentName name,
|
private final ServiceRecord findServiceLocked(ComponentName name,
|
||||||
IBinder token, int userId) {
|
IBinder token, int userId) {
|
||||||
ServiceRecord r = mServiceMap.getServiceByName(name, userId);
|
ServiceRecord r = getServiceByName(name, userId);
|
||||||
return r == token ? r : null;
|
return r == token ? r : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,12 +875,14 @@ public final class ActiveServices {
|
|||||||
userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
|
userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
|
||||||
false, true, "service", null);
|
false, true, "service", null);
|
||||||
|
|
||||||
if (service.getComponent() != null) {
|
ServiceMap smap = getServiceMap(userId);
|
||||||
r = mServiceMap.getServiceByName(service.getComponent(), userId);
|
final ComponentName comp = service.getComponent();
|
||||||
|
if (comp != null) {
|
||||||
|
r = smap.mServicesByName.get(comp);
|
||||||
}
|
}
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
Intent.FilterComparison filter = new Intent.FilterComparison(service);
|
Intent.FilterComparison filter = new Intent.FilterComparison(service);
|
||||||
r = mServiceMap.getServiceByIntent(filter, userId);
|
r = smap.mServicesByIntent.get(filter);
|
||||||
}
|
}
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
try {
|
try {
|
||||||
@@ -777,14 +903,15 @@ public final class ActiveServices {
|
|||||||
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
|
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
|
||||||
sInfo.name, sInfo.flags)) {
|
sInfo.name, sInfo.flags)) {
|
||||||
userId = 0;
|
userId = 0;
|
||||||
|
smap = getServiceMap(0);
|
||||||
}
|
}
|
||||||
sInfo = new ServiceInfo(sInfo);
|
sInfo = new ServiceInfo(sInfo);
|
||||||
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
|
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
|
||||||
}
|
}
|
||||||
r = mServiceMap.getServiceByName(name, userId);
|
r = smap.mServicesByName.get(name);
|
||||||
if (r == null && createIfNeeded) {
|
if (r == null && createIfNeeded) {
|
||||||
Intent.FilterComparison filter = new Intent.FilterComparison(
|
Intent.FilterComparison filter
|
||||||
service.cloneFilter());
|
= new Intent.FilterComparison(service.cloneFilter());
|
||||||
ServiceRestarter res = new ServiceRestarter();
|
ServiceRestarter res = new ServiceRestarter();
|
||||||
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
|
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
|
||||||
BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
|
BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
|
||||||
@@ -795,8 +922,8 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
|
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
|
||||||
res.setService(r);
|
res.setService(r);
|
||||||
mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
|
smap.mServicesByName.put(name, r);
|
||||||
mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
|
smap.mServicesByIntent.put(filter, r);
|
||||||
|
|
||||||
// Make sure this component isn't in the pending list.
|
// Make sure this component isn't in the pending list.
|
||||||
int N = mPendingServices.size();
|
int N = mPendingServices.size();
|
||||||
@@ -842,9 +969,9 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
|
private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
|
||||||
if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
|
if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING "
|
||||||
+ why + " of " + r + " in app " + r.app);
|
+ why + " of " + r + " in app " + r.app);
|
||||||
else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
|
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, ">>> EXECUTING "
|
||||||
+ why + " of " + r.shortName);
|
+ why + " of " + r.shortName);
|
||||||
long now = SystemClock.uptimeMillis();
|
long now = SystemClock.uptimeMillis();
|
||||||
if (r.executeNesting == 0) {
|
if (r.executeNesting == 0) {
|
||||||
@@ -1052,6 +1179,13 @@ public final class ActiveServices {
|
|||||||
// restarting state.
|
// restarting state.
|
||||||
mRestartingServices.remove(r);
|
mRestartingServices.remove(r);
|
||||||
|
|
||||||
|
// Make sure this service is no longer considered delayed, we are starting it now.
|
||||||
|
if (r.delayed) {
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "REM FR DELAY LIST (bring up): " + r);
|
||||||
|
getServiceMap(r.userId).mDelayedStartList.remove(r);
|
||||||
|
r.delayed = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the user who owns this service is started. If not,
|
// Make sure that the user who owns this service is started. If not,
|
||||||
// we don't want to allow it to run.
|
// we don't want to allow it to run.
|
||||||
if (mAm.mStartedUsers.get(r.userId) == null) {
|
if (mAm.mStartedUsers.get(r.userId) == null) {
|
||||||
@@ -1126,6 +1260,15 @@ public final class ActiveServices {
|
|||||||
mPendingServices.add(r);
|
mPendingServices.add(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r.delayedStop) {
|
||||||
|
// Oh and hey we've already been asked to stop!
|
||||||
|
r.delayedStop = false;
|
||||||
|
if (r.startRequested) {
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Applying delayed stop (in bring up): " + r);
|
||||||
|
stopServiceLocked(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1188,6 +1331,21 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendServiceArgsLocked(r, execInFg, true);
|
sendServiceArgsLocked(r, execInFg, true);
|
||||||
|
|
||||||
|
if (r.delayed) {
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "REM FR DELAY LIST (new proc): " + r);
|
||||||
|
getServiceMap(r.userId).mDelayedStartList.remove(r);
|
||||||
|
r.delayed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.delayedStop) {
|
||||||
|
// Oh and hey we've already been asked to stop!
|
||||||
|
r.delayedStop = false;
|
||||||
|
if (r.startRequested) {
|
||||||
|
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Applying delayed stop (from start): " + r);
|
||||||
|
stopServiceLocked(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
|
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
|
||||||
@@ -1246,11 +1404,12 @@ public final class ActiveServices {
|
|||||||
//Slog.i(TAG, "Bring down service:");
|
//Slog.i(TAG, "Bring down service:");
|
||||||
//r.dump(" ");
|
//r.dump(" ");
|
||||||
|
|
||||||
// Does it still need to run?
|
// Are we still explicitly being asked to run?
|
||||||
if (r.startRequested) {
|
if (r.startRequested) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is someone still bound to us keepign us running?
|
||||||
if (!knowConn) {
|
if (!knowConn) {
|
||||||
hasConn = r.hasAutoCreateConnections();
|
hasConn = r.hasAutoCreateConnections();
|
||||||
}
|
}
|
||||||
@@ -1258,6 +1417,11 @@ public final class ActiveServices {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Are we in the process of launching?
|
||||||
|
if (mPendingServices.contains(r)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bringDownServiceLocked(r);
|
bringDownServiceLocked(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1310,8 +1474,9 @@ public final class ActiveServices {
|
|||||||
EventLogTags.writeAmDestroyService(
|
EventLogTags.writeAmDestroyService(
|
||||||
r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
|
r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
|
||||||
|
|
||||||
mServiceMap.removeServiceByName(r.name, r.userId);
|
final ServiceMap smap = getServiceMap(r.userId);
|
||||||
mServiceMap.removeServiceByIntent(r.intent, r.userId);
|
smap.mServicesByName.remove(r.name);
|
||||||
|
smap.mServicesByIntent.remove(r.intent);
|
||||||
r.totalRestartCount = 0;
|
r.totalRestartCount = 0;
|
||||||
unscheduleServiceRestartLocked(r);
|
unscheduleServiceRestartLocked(r);
|
||||||
|
|
||||||
@@ -1379,6 +1544,8 @@ public final class ActiveServices {
|
|||||||
r.tracker = null;
|
r.tracker = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smap.ensureNotStartingBackground(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeConnectionLocked(
|
void removeConnectionLocked(
|
||||||
@@ -1617,10 +1784,11 @@ public final class ActiveServices {
|
|||||||
|
|
||||||
private boolean collectForceStopServicesLocked(String name, int userId,
|
private boolean collectForceStopServicesLocked(String name, int userId,
|
||||||
boolean evenPersistent, boolean doit,
|
boolean evenPersistent, boolean doit,
|
||||||
HashMap<ComponentName, ServiceRecord> services,
|
ArrayMap<ComponentName, ServiceRecord> services,
|
||||||
ArrayList<ServiceRecord> result) {
|
ArrayList<ServiceRecord> result) {
|
||||||
boolean didSomething = false;
|
boolean didSomething = false;
|
||||||
for (ServiceRecord service : services.values()) {
|
for (int i=0; i<services.size(); i++) {
|
||||||
|
ServiceRecord service = services.valueAt(i);
|
||||||
if ((name == null || service.packageName.equals(name))
|
if ((name == null || service.packageName.equals(name))
|
||||||
&& (service.app == null || evenPersistent || !service.app.persistent)) {
|
&& (service.app == null || evenPersistent || !service.app.persistent)) {
|
||||||
if (!doit) {
|
if (!doit) {
|
||||||
@@ -1643,17 +1811,17 @@ public final class ActiveServices {
|
|||||||
boolean didSomething = false;
|
boolean didSomething = false;
|
||||||
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
|
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
|
||||||
if (userId == UserHandle.USER_ALL) {
|
if (userId == UserHandle.USER_ALL) {
|
||||||
for (int i=0; i<mServiceMap.mServicesByNamePerUser.size(); i++) {
|
for (int i=0; i<mServiceMap.size(); i++) {
|
||||||
didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
|
didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
|
||||||
doit, mServiceMap.mServicesByNamePerUser.valueAt(i), services);
|
doit, mServiceMap.valueAt(i).mServicesByName, services);
|
||||||
if (!doit && didSomething) {
|
if (!doit && didSomething) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
HashMap<ComponentName, ServiceRecord> items
|
ServiceMap smap = mServiceMap.valueAt(userId);
|
||||||
= mServiceMap.mServicesByNamePerUser.get(userId);
|
if (smap != null) {
|
||||||
if (items != null) {
|
ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
|
||||||
didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
|
didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
|
||||||
doit, items, services);
|
doit, items, services);
|
||||||
}
|
}
|
||||||
@@ -1668,7 +1836,9 @@ public final class ActiveServices {
|
|||||||
|
|
||||||
void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
|
void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
|
||||||
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
|
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
|
||||||
for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
|
ArrayMap<ComponentName, ServiceRecord> alls = getServices(tr.userId);
|
||||||
|
for (int i=0; i<alls.size(); i++) {
|
||||||
|
ServiceRecord sr = alls.valueAt(i);
|
||||||
if (sr.packageName.equals(component.getPackageName())) {
|
if (sr.packageName.equals(component.getPackageName())) {
|
||||||
services.add(sr);
|
services.add(sr);
|
||||||
}
|
}
|
||||||
@@ -1862,12 +2032,10 @@ public final class ActiveServices {
|
|||||||
uid) == PackageManager.PERMISSION_GRANTED) {
|
uid) == PackageManager.PERMISSION_GRANTED) {
|
||||||
int[] users = mAm.getUsersLocked();
|
int[] users = mAm.getUsersLocked();
|
||||||
for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
|
for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
|
||||||
if (mServiceMap.getAllServices(users[ui]).size() > 0) {
|
ArrayMap<ComponentName, ServiceRecord> alls = getServices(users[ui]);
|
||||||
Iterator<ServiceRecord> it = mServiceMap.getAllServices(
|
for (int i=0; i<alls.size() && res.size() < maxNum; i++) {
|
||||||
users[ui]).iterator();
|
ServiceRecord sr = alls.valueAt(i);
|
||||||
while (it.hasNext() && res.size() < maxNum) {
|
res.add(makeRunningServiceInfoLocked(sr));
|
||||||
res.add(makeRunningServiceInfoLocked(it.next()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1880,12 +2048,10 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int userId = UserHandle.getUserId(uid);
|
int userId = UserHandle.getUserId(uid);
|
||||||
if (mServiceMap.getAllServices(userId).size() > 0) {
|
ArrayMap<ComponentName, ServiceRecord> alls = getServices(userId);
|
||||||
Iterator<ServiceRecord> it
|
for (int i=0; i<alls.size() && res.size() < maxNum; i++) {
|
||||||
= mServiceMap.getAllServices(userId).iterator();
|
ServiceRecord sr = alls.valueAt(i);
|
||||||
while (it.hasNext() && res.size() < maxNum) {
|
res.add(makeRunningServiceInfoLocked(sr));
|
||||||
res.add(makeRunningServiceInfoLocked(it.next()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
|
for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
|
||||||
@@ -1907,7 +2073,7 @@ public final class ActiveServices {
|
|||||||
|
|
||||||
public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
|
public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
|
||||||
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||||
ServiceRecord r = mServiceMap.getServiceByName(name, userId);
|
ServiceRecord r = getServiceByName(name, userId);
|
||||||
if (r != null) {
|
if (r != null) {
|
||||||
for (int conni=r.connections.size()-1; conni>=0; conni--) {
|
for (int conni=r.connections.size()-1; conni>=0; conni--) {
|
||||||
ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
|
ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
|
||||||
@@ -1974,28 +2140,27 @@ public final class ActiveServices {
|
|||||||
try {
|
try {
|
||||||
int[] users = mAm.getUsersLocked();
|
int[] users = mAm.getUsersLocked();
|
||||||
for (int user : users) {
|
for (int user : users) {
|
||||||
if (mServiceMap.getAllServices(user).size() > 0) {
|
ServiceMap smap = getServiceMap(user);
|
||||||
boolean printed = false;
|
boolean printed = false;
|
||||||
|
if (smap.mServicesByName.size() > 0) {
|
||||||
long nowReal = SystemClock.elapsedRealtime();
|
long nowReal = SystemClock.elapsedRealtime();
|
||||||
Iterator<ServiceRecord> it = mServiceMap.getAllServices(
|
|
||||||
user).iterator();
|
|
||||||
needSep = false;
|
needSep = false;
|
||||||
while (it.hasNext()) {
|
for (int si=0; si<smap.mServicesByName.size(); si++) {
|
||||||
ServiceRecord r = it.next();
|
ServiceRecord r = smap.mServicesByName.valueAt(si);
|
||||||
if (!matcher.match(r, r.name)) {
|
if (!matcher.match(r, r.name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
|
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printedAnything = true;
|
|
||||||
if (!printed) {
|
if (!printed) {
|
||||||
if (user != 0) {
|
if (printedAnything) {
|
||||||
pw.println();
|
pw.println();
|
||||||
}
|
}
|
||||||
pw.println(" User " + user + " active services:");
|
pw.println(" User " + user + " active services:");
|
||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
|
printedAnything = true;
|
||||||
if (needSep) {
|
if (needSep) {
|
||||||
pw.println();
|
pw.println();
|
||||||
}
|
}
|
||||||
@@ -2054,9 +2219,47 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
needSep |= printed;
|
needSep |= printed;
|
||||||
}
|
}
|
||||||
|
printed = false;
|
||||||
|
for (int si=0, SN=smap.mDelayedStartList.size(); si<SN; si++) {
|
||||||
|
ServiceRecord r = smap.mDelayedStartList.get(si);
|
||||||
|
if (!matcher.match(r, r.name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!printed) {
|
||||||
|
if (printedAnything) {
|
||||||
|
pw.println();
|
||||||
|
}
|
||||||
|
pw.println(" User " + user + " delayed start services:");
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
printedAnything = true;
|
||||||
|
pw.print(" * Delayed start "); pw.println(r);
|
||||||
|
}
|
||||||
|
printed = false;
|
||||||
|
for (int si=0, SN=smap.mStartingBackground.size(); si<SN; si++) {
|
||||||
|
ServiceRecord r = smap.mStartingBackground.get(si);
|
||||||
|
if (!matcher.match(r, r.name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!printed) {
|
||||||
|
if (printedAnything) {
|
||||||
|
pw.println();
|
||||||
|
}
|
||||||
|
pw.println(" User " + user + " starting in background:");
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
printedAnything = true;
|
||||||
|
pw.print(" * Starting bg "); pw.println(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Exception in dumpServicesLocked", e);
|
Slog.w(TAG, "Exception in dumpServicesLocked", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPendingServices.size() > 0) {
|
if (mPendingServices.size() > 0) {
|
||||||
@@ -2129,31 +2332,27 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dumpAll) {
|
if (dumpAll) {
|
||||||
if (mServiceConnections.size() > 0) {
|
boolean printed = false;
|
||||||
boolean printed = false;
|
for (int ic=0; ic<mServiceConnections.size(); ic++) {
|
||||||
Iterator<ArrayList<ConnectionRecord>> it
|
ArrayList<ConnectionRecord> r = mServiceConnections.valueAt(ic);
|
||||||
= mServiceConnections.values().iterator();
|
for (int i=0; i<r.size(); i++) {
|
||||||
while (it.hasNext()) {
|
ConnectionRecord cr = r.get(i);
|
||||||
ArrayList<ConnectionRecord> r = it.next();
|
if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
|
||||||
for (int i=0; i<r.size(); i++) {
|
continue;
|
||||||
ConnectionRecord cr = r.get(i);
|
|
||||||
if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (dumpPackage != null && (cr.binding.client == null
|
|
||||||
|| !dumpPackage.equals(cr.binding.client.info.packageName))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printedAnything = true;
|
|
||||||
if (!printed) {
|
|
||||||
if (needSep) pw.println();
|
|
||||||
needSep = true;
|
|
||||||
pw.println(" Connection bindings to services:");
|
|
||||||
printed = true;
|
|
||||||
}
|
|
||||||
pw.print(" * "); pw.println(cr);
|
|
||||||
cr.dump(pw, " ");
|
|
||||||
}
|
}
|
||||||
|
if (dumpPackage != null && (cr.binding.client == null
|
||||||
|
|| !dumpPackage.equals(cr.binding.client.info.packageName))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printedAnything = true;
|
||||||
|
if (!printed) {
|
||||||
|
if (needSep) pw.println();
|
||||||
|
needSep = true;
|
||||||
|
pw.println(" Connection bindings to services:");
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
pw.print(" * "); pw.println(cr);
|
||||||
|
cr.dump(pw, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2179,7 +2378,9 @@ public final class ActiveServices {
|
|||||||
int[] users = mAm.getUsersLocked();
|
int[] users = mAm.getUsersLocked();
|
||||||
if ("all".equals(name)) {
|
if ("all".equals(name)) {
|
||||||
for (int user : users) {
|
for (int user : users) {
|
||||||
for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
|
ArrayMap<ComponentName, ServiceRecord> alls = getServices(user);
|
||||||
|
for (int i=0; i<alls.size(); i++) {
|
||||||
|
ServiceRecord r1 = alls.valueAt(i);
|
||||||
services.add(r1);
|
services.add(r1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2198,7 +2399,9 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int user : users) {
|
for (int user : users) {
|
||||||
for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
|
ArrayMap<ComponentName, ServiceRecord> alls = getServices(user);
|
||||||
|
for (int i=0; i<alls.size(); i++) {
|
||||||
|
ServiceRecord r1 = alls.valueAt(i);
|
||||||
if (componentName != null) {
|
if (componentName != null) {
|
||||||
if (r1.name.equals(componentName)) {
|
if (r1.name.equals(componentName)) {
|
||||||
services.add(r1);
|
services.add(r1);
|
||||||
|
|||||||
@@ -527,7 +527,33 @@ final class ProcessRecord {
|
|||||||
sb.append('}');
|
sb.append('}');
|
||||||
return stringName = sb.toString();
|
return stringName = sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String makeAdjReason() {
|
||||||
|
StringBuilder sb = new StringBuilder(128);
|
||||||
|
sb.append('(').append(adjType).append(')');
|
||||||
|
if (adjSource != null || adjTarget != null) {
|
||||||
|
sb.append(' ');
|
||||||
|
if (adjTarget instanceof ComponentName) {
|
||||||
|
sb.append(((ComponentName)adjTarget).flattenToShortString());
|
||||||
|
} else if (adjTarget != null) {
|
||||||
|
sb.append(adjTarget.toString());
|
||||||
|
} else {
|
||||||
|
sb.append("{null}");
|
||||||
|
}
|
||||||
|
sb.append("<=");
|
||||||
|
if (adjSource instanceof ProcessRecord) {
|
||||||
|
sb.append("Proc{");
|
||||||
|
sb.append(((ProcessRecord)adjSource).toShortString());
|
||||||
|
sb.append("}");
|
||||||
|
} else if (adjSource != null) {
|
||||||
|
sb.append(adjSource.toString());
|
||||||
|
} else {
|
||||||
|
sb.append("{null}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if package has been added false if not
|
* Return true if package has been added false if not
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -85,11 +85,14 @@ final class ServiceRecord extends Binder {
|
|||||||
ProcessRecord app; // where this service is running or null.
|
ProcessRecord app; // where this service is running or null.
|
||||||
ProcessRecord isolatedProc; // keep track of isolated process, if requested
|
ProcessRecord isolatedProc; // keep track of isolated process, if requested
|
||||||
ProcessStats.ServiceState tracker; // tracking service execution, may be null
|
ProcessStats.ServiceState tracker; // tracking service execution, may be null
|
||||||
|
boolean delayed; // are we waiting to start this service in the background?
|
||||||
boolean isForeground; // is service currently in foreground mode?
|
boolean isForeground; // is service currently in foreground mode?
|
||||||
int foregroundId; // Notification ID of last foreground req.
|
int foregroundId; // Notification ID of last foreground req.
|
||||||
Notification foregroundNoti; // Notification record of foreground state.
|
Notification foregroundNoti; // Notification record of foreground state.
|
||||||
long lastActivity; // last time there was some activity on the service.
|
long lastActivity; // last time there was some activity on the service.
|
||||||
|
long startingBgTimeout; // time at which we scheduled this for a delayed start.
|
||||||
boolean startRequested; // someone explicitly called start?
|
boolean startRequested; // someone explicitly called start?
|
||||||
|
boolean delayedStop; // service has been stopped but is in a delayed start?
|
||||||
boolean stopIfKilled; // last onStart() said to stop if service killed?
|
boolean stopIfKilled; // last onStart() said to stop if service killed?
|
||||||
boolean callStart; // last onStart() has asked to alway be called on restart.
|
boolean callStart; // last onStart() has asked to alway be called on restart.
|
||||||
int executeNesting; // number of outstanding operations keeping foreground.
|
int executeNesting; // number of outstanding operations keeping foreground.
|
||||||
@@ -220,6 +223,9 @@ final class ServiceRecord extends Binder {
|
|||||||
if (isolatedProc != null) {
|
if (isolatedProc != null) {
|
||||||
pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
|
pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
|
||||||
}
|
}
|
||||||
|
if (delayed) {
|
||||||
|
pw.print(prefix); pw.print("delayed="); pw.println(delayed);
|
||||||
|
}
|
||||||
if (isForeground || foregroundId != 0) {
|
if (isForeground || foregroundId != 0) {
|
||||||
pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
|
pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
|
||||||
pw.print(" foregroundId="); pw.print(foregroundId);
|
pw.print(" foregroundId="); pw.print(foregroundId);
|
||||||
@@ -227,14 +233,17 @@ final class ServiceRecord extends Binder {
|
|||||||
}
|
}
|
||||||
pw.print(prefix); pw.print("createTime=");
|
pw.print(prefix); pw.print("createTime=");
|
||||||
TimeUtils.formatDuration(createTime, nowReal, pw);
|
TimeUtils.formatDuration(createTime, nowReal, pw);
|
||||||
pw.print(" lastActivity=");
|
pw.print(" startingBgTimeout=");
|
||||||
TimeUtils.formatDuration(lastActivity, now, pw);
|
TimeUtils.formatDuration(startingBgTimeout, now, pw);
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.print(prefix); pw.print("restartTime=");
|
pw.print(prefix); pw.print("lastActivity=");
|
||||||
|
TimeUtils.formatDuration(lastActivity, now, pw);
|
||||||
|
pw.print(" restartTime=");
|
||||||
TimeUtils.formatDuration(restartTime, now, pw);
|
TimeUtils.formatDuration(restartTime, now, pw);
|
||||||
pw.print(" createdFromFg="); pw.println(createdFromFg);
|
pw.print(" createdFromFg="); pw.println(createdFromFg);
|
||||||
if (startRequested || lastStartId != 0) {
|
if (startRequested || delayedStop || lastStartId != 0) {
|
||||||
pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
|
pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
|
||||||
|
pw.print(" delayedStop="); pw.print(delayedStop);
|
||||||
pw.print(" stopIfKilled="); pw.print(stopIfKilled);
|
pw.print(" stopIfKilled="); pw.print(stopIfKilled);
|
||||||
pw.print(" callStart="); pw.print(callStart);
|
pw.print(" callStart="); pw.print(callStart);
|
||||||
pw.print(" lastStartId="); pw.println(lastStartId);
|
pw.print(" lastStartId="); pw.println(lastStartId);
|
||||||
|
|||||||
Reference in New Issue
Block a user