1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import android.content.IIntentReceiver;
20import android.content.ComponentName;
21import android.content.Intent;
22import android.content.pm.ActivityInfo;
23import android.content.pm.ResolveInfo;
24import android.os.Binder;
25import android.os.Bundle;
26import android.os.IBinder;
27import android.os.SystemClock;
28import android.util.PrintWriterPrinter;
29
30import java.io.PrintWriter;
31import java.util.List;
32
33/**
34 * An active intent broadcast.
35 */
36class BroadcastRecord extends Binder {
37    final Intent intent;    // the original intent that generated us
38    final ProcessRecord callerApp; // process that sent this
39    final String callerPackage; // who sent this
40    final int callingPid;   // the pid of who sent this
41    final int callingUid;   // the uid of who sent this
42    final boolean ordered;  // serialize the send to receivers?
43    final boolean sticky;   // originated from existing sticky data?
44    final boolean initialSticky; // initial broadcast from register to sticky?
45    final String requiredPermission; // a permission the caller has required
46    final List receivers;   // contains BroadcastFilter and ResolveInfo
47    final IIntentReceiver resultTo; // who receives final result if non-null
48    long dispatchTime;      // when dispatch started on this set of receivers
49    long receiverTime;      // when current receiver started for timeouts.
50    long finishTime;        // when we finished the broadcast.
51    int resultCode;         // current result code value.
52    String resultData;      // current result data value.
53    Bundle resultExtras;    // current result extra data values.
54    boolean resultAbort;    // current result abortBroadcast value.
55    int nextReceiver;       // next receiver to be executed.
56    IBinder receiver;       // who is currently running, null if none.
57    int state;
58    int anrCount;           // has this broadcast record hit any ANRs?
59
60    static final int IDLE = 0;
61    static final int APP_RECEIVE = 1;
62    static final int CALL_IN_RECEIVE = 2;
63    static final int CALL_DONE_RECEIVE = 3;
64
65    // The following are set when we are calling a receiver (one that
66    // was found in our list of registered receivers).
67    BroadcastFilter curFilter;
68
69    // The following are set only when we are launching a receiver (one
70    // that was found by querying the package manager).
71    ProcessRecord curApp;       // hosting application of current receiver.
72    ComponentName curComponent; // the receiver class that is currently running.
73    ActivityInfo curReceiver;   // info about the receiver that is currently running.
74
75    void dump(PrintWriter pw, String prefix) {
76        pw.println(prefix + this);
77        pw.println(prefix + intent);
78        if (sticky) {
79            Bundle bundle = intent.getExtras();
80            if (bundle != null) {
81                pw.println(prefix + "extras: " + bundle.toString());
82            }
83        }
84        pw.println(prefix + "proc=" + callerApp);
85        pw.println(prefix + "caller=" + callerPackage
86                + " callingPid=" + callingPid
87                + " callingUid=" + callingUid);
88        if (requiredPermission != null) {
89            pw.println(prefix + "requiredPermission=" + requiredPermission);
90        }
91        pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
92                + (SystemClock.uptimeMillis()-dispatchTime) + "ms since now)");
93        if (finishTime != 0) {
94            pw.println(prefix + "finishTime=" + finishTime + " ("
95                    + (SystemClock.uptimeMillis()-finishTime) + "ms since now)");
96        } else {
97            pw.println(prefix + "receiverTime=" + receiverTime + " ("
98                    + (SystemClock.uptimeMillis()-receiverTime) + "ms since now)");
99        }
100        if (anrCount != 0) {
101            pw.println(prefix + "anrCount=" + anrCount);
102        }
103        if (resultTo != null || resultCode != -1 || resultData != null) {
104            pw.println(prefix + "resultTo=" + resultTo
105                  + " resultCode=" + resultCode + " resultData=" + resultData);
106        }
107        if (resultExtras != null) {
108            pw.println(prefix + "resultExtras=" + resultExtras);
109        }
110        if (resultAbort || ordered || sticky || initialSticky) {
111            pw.println(prefix + "resultAbort=" + resultAbort
112                    + " ordered=" + ordered + " sticky=" + sticky
113                    + " initialSticky=" + initialSticky);
114        }
115        if (nextReceiver != 0 || receiver != null) {
116            pw.println(prefix + "nextReceiver=" + nextReceiver
117                  + " receiver=" + receiver);
118        }
119        if (curFilter != null) {
120            pw.println(prefix + "curFilter=" + curFilter);
121        }
122        if (curReceiver != null) {
123            pw.println(prefix + "curReceiver=" + curReceiver);
124        }
125        if (curApp != null) {
126            pw.println(prefix + "curApp=" + curApp);
127            pw.println(prefix + "curComponent="
128                    + (curComponent != null ? curComponent.toShortString() : "--"));
129            if (curReceiver != null && curReceiver.applicationInfo != null) {
130                pw.println(prefix + "curSourceDir=" + curReceiver.applicationInfo.sourceDir);
131            }
132        }
133        String stateStr = " (?)";
134        switch (state) {
135            case IDLE:              stateStr=" (IDLE)"; break;
136            case APP_RECEIVE:       stateStr=" (APP_RECEIVE)"; break;
137            case CALL_IN_RECEIVE:   stateStr=" (CALL_IN_RECEIVE)"; break;
138            case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
139        }
140        pw.println(prefix + "state=" + state + stateStr);
141        final int N = receivers != null ? receivers.size() : 0;
142        String p2 = prefix + "  ";
143        PrintWriterPrinter printer = new PrintWriterPrinter(pw);
144        for (int i=0; i<N; i++) {
145            Object o = receivers.get(i);
146            pw.println(prefix + "Receiver #" + i + ": " + o);
147            if (o instanceof BroadcastFilter)
148                ((BroadcastFilter)o).dumpBrief(pw, p2);
149            else if (o instanceof ResolveInfo)
150                ((ResolveInfo)o).dump(printer, p2);
151        }
152    }
153
154    BroadcastRecord(Intent _intent, ProcessRecord _callerApp, String _callerPackage,
155            int _callingPid, int _callingUid, String _requiredPermission,
156            List _receivers, IIntentReceiver _resultTo, int _resultCode,
157            String _resultData, Bundle _resultExtras, boolean _serialized,
158            boolean _sticky, boolean _initialSticky) {
159        intent = _intent;
160        callerApp = _callerApp;
161        callerPackage = _callerPackage;
162        callingPid = _callingPid;
163        callingUid = _callingUid;
164        requiredPermission = _requiredPermission;
165        receivers = _receivers;
166        resultTo = _resultTo;
167        resultCode = _resultCode;
168        resultData = _resultData;
169        resultExtras = _resultExtras;
170        ordered = _serialized;
171        sticky = _sticky;
172        initialSticky = _initialSticky;
173        nextReceiver = 0;
174        state = IDLE;
175    }
176
177    public String toString() {
178        return "BroadcastRecord{"
179            + Integer.toHexString(System.identityHashCode(this))
180            + " " + intent.getAction() + "}";
181    }
182}
183