blob: c3f0b3e8de58b16a67375bb072b125653ca17bed [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.am;
import android.content.IIntentReceiver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.PrintWriterPrinter;
import java.io.PrintWriter;
import java.util.List;
/**
* An active intent broadcast.
*/
class BroadcastRecord extends Binder {
final Intent intent; // the original intent that generated us
final ProcessRecord callerApp; // process that sent this
final String callerPackage; // who sent this
final int callingPid; // the pid of who sent this
final int callingUid; // the uid of who sent this
final boolean ordered; // serialize the send to receivers?
final boolean sticky; // originated from existing sticky data?
final boolean initialSticky; // initial broadcast from register to sticky?
final String requiredPermission; // a permission the caller has required
final List receivers; // contains BroadcastFilter and ResolveInfo
final IIntentReceiver resultTo; // who receives final result if non-null
long dispatchTime; // when dispatch started on this set of receivers
long receiverTime; // when current receiver started for timeouts.
long finishTime; // when we finished the broadcast.
int resultCode; // current result code value.
String resultData; // current result data value.
Bundle resultExtras; // current result extra data values.
boolean resultAbort; // current result abortBroadcast value.
int nextReceiver; // next receiver to be executed.
IBinder receiver; // who is currently running, null if none.
int state;
int anrCount; // has this broadcast record hit any ANRs?
static final int IDLE = 0;
static final int APP_RECEIVE = 1;
static final int CALL_IN_RECEIVE = 2;
static final int CALL_DONE_RECEIVE = 3;
// The following are set when we are calling a receiver (one that
// was found in our list of registered receivers).
BroadcastFilter curFilter;
// The following are set only when we are launching a receiver (one
// that was found by querying the package manager).
ProcessRecord curApp; // hosting application of current receiver.
ComponentName curComponent; // the receiver class that is currently running.
ActivityInfo curReceiver; // info about the receiver that is currently running.
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
pw.println(prefix + intent);
if (sticky) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
pw.println(prefix + "extras: " + bundle.toString());
}
}
pw.println(prefix + "proc=" + callerApp);
pw.println(prefix + "caller=" + callerPackage
+ " callingPid=" + callingPid
+ " callingUid=" + callingUid);
if (requiredPermission != null) {
pw.println(prefix + "requiredPermission=" + requiredPermission);
}
pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
+ (SystemClock.uptimeMillis()-dispatchTime) + "ms since now)");
if (finishTime != 0) {
pw.println(prefix + "finishTime=" + finishTime + " ("
+ (SystemClock.uptimeMillis()-finishTime) + "ms since now)");
} else {
pw.println(prefix + "receiverTime=" + receiverTime + " ("
+ (SystemClock.uptimeMillis()-receiverTime) + "ms since now)");
}
if (anrCount != 0) {
pw.println(prefix + "anrCount=" + anrCount);
}
if (resultTo != null || resultCode != -1 || resultData != null) {
pw.println(prefix + "resultTo=" + resultTo
+ " resultCode=" + resultCode + " resultData=" + resultData);
}
if (resultExtras != null) {
pw.println(prefix + "resultExtras=" + resultExtras);
}
if (resultAbort || ordered || sticky || initialSticky) {
pw.println(prefix + "resultAbort=" + resultAbort
+ " ordered=" + ordered + " sticky=" + sticky
+ " initialSticky=" + initialSticky);
}
if (nextReceiver != 0 || receiver != null) {
pw.println(prefix + "nextReceiver=" + nextReceiver
+ " receiver=" + receiver);
}
if (curFilter != null) {
pw.println(prefix + "curFilter=" + curFilter);
}
if (curReceiver != null) {
pw.println(prefix + "curReceiver=" + curReceiver);
}
if (curApp != null) {
pw.println(prefix + "curApp=" + curApp);
pw.println(prefix + "curComponent="
+ (curComponent != null ? curComponent.toShortString() : "--"));
if (curReceiver != null && curReceiver.applicationInfo != null) {
pw.println(prefix + "curSourceDir=" + curReceiver.applicationInfo.sourceDir);
}
}
String stateStr = " (?)";
switch (state) {
case IDLE: stateStr=" (IDLE)"; break;
case APP_RECEIVE: stateStr=" (APP_RECEIVE)"; break;
case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break;
case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
}
pw.println(prefix + "state=" + state + stateStr);
final int N = receivers != null ? receivers.size() : 0;
String p2 = prefix + " ";
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
for (int i=0; i<N; i++) {
Object o = receivers.get(i);
pw.println(prefix + "Receiver #" + i + ": " + o);
if (o instanceof BroadcastFilter)
((BroadcastFilter)o).dumpBrief(pw, p2);
else if (o instanceof ResolveInfo)
((ResolveInfo)o).dump(printer, p2);
}
}
BroadcastRecord(Intent _intent, ProcessRecord _callerApp, String _callerPackage,
int _callingPid, int _callingUid, String _requiredPermission,
List _receivers, IIntentReceiver _resultTo, int _resultCode,
String _resultData, Bundle _resultExtras, boolean _serialized,
boolean _sticky, boolean _initialSticky) {
intent = _intent;
callerApp = _callerApp;
callerPackage = _callerPackage;
callingPid = _callingPid;
callingUid = _callingUid;
requiredPermission = _requiredPermission;
receivers = _receivers;
resultTo = _resultTo;
resultCode = _resultCode;
resultData = _resultData;
resultExtras = _resultExtras;
ordered = _serialized;
sticky = _sticky;
initialSticky = _initialSticky;
nextReceiver = 0;
state = IDLE;
}
public String toString() {
return "BroadcastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + intent.getAction() + "}";
}
}