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 
17 package com.android.server.am;
18 
19 import android.app.IServiceConnection;
20 import android.app.PendingIntent;
21 import android.content.Context;
22 import android.util.proto.ProtoOutputStream;
23 import android.util.proto.ProtoUtils;
24 
25 import java.io.PrintWriter;
26 
27 /**
28  * Description of a single binding to a service.
29  */
30 final class ConnectionRecord {
31     final AppBindRecord binding;    // The application/service binding.
32     final ActivityRecord activity;  // If non-null, the owning activity.
33     final IServiceConnection conn;  // The client connection.
34     final int flags;                // Binding options.
35     final int clientLabel;          // String resource labeling this client.
36     final PendingIntent clientIntent; // How to launch the client.
37     String stringName;              // Caching of toString.
38     boolean serviceDead;            // Well is it?
39 
40     // Please keep the following two enum list synced.
41     private static int[] BIND_ORIG_ENUMS = new int[] {
42             Context.BIND_AUTO_CREATE,
43             Context.BIND_DEBUG_UNBIND,
44             Context.BIND_NOT_FOREGROUND,
45             Context.BIND_IMPORTANT_BACKGROUND,
46             Context.BIND_ABOVE_CLIENT,
47             Context.BIND_ALLOW_OOM_MANAGEMENT,
48             Context.BIND_WAIVE_PRIORITY,
49             Context.BIND_IMPORTANT,
50             Context.BIND_ADJUST_WITH_ACTIVITY,
51             Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
52             Context.BIND_FOREGROUND_SERVICE,
53             Context.BIND_TREAT_LIKE_ACTIVITY,
54             Context.BIND_VISIBLE,
55             Context.BIND_SHOWING_UI,
56             Context.BIND_NOT_VISIBLE,
57     };
58     private static int[] BIND_PROTO_ENUMS = new int[] {
59             ConnectionRecordProto.AUTO_CREATE,
60             ConnectionRecordProto.DEBUG_UNBIND,
61             ConnectionRecordProto.NOT_FG,
62             ConnectionRecordProto.IMPORTANT_BG,
63             ConnectionRecordProto.ABOVE_CLIENT,
64             ConnectionRecordProto.ALLOW_OOM_MANAGEMENT,
65             ConnectionRecordProto.WAIVE_PRIORITY,
66             ConnectionRecordProto.IMPORTANT,
67             ConnectionRecordProto.ADJUST_WITH_ACTIVITY,
68             ConnectionRecordProto.FG_SERVICE_WHILE_AWAKE,
69             ConnectionRecordProto.FG_SERVICE,
70             ConnectionRecordProto.TREAT_LIKE_ACTIVITY,
71             ConnectionRecordProto.VISIBLE,
72             ConnectionRecordProto.SHOWING_UI,
73             ConnectionRecordProto.NOT_VISIBLE,
74     };
75 
dump(PrintWriter pw, String prefix)76     void dump(PrintWriter pw, String prefix) {
77         pw.println(prefix + "binding=" + binding);
78         if (activity != null) {
79             pw.println(prefix + "activity=" + activity);
80         }
81         pw.println(prefix + "conn=" + conn.asBinder()
82                 + " flags=0x" + Integer.toHexString(flags));
83     }
84 
ConnectionRecord(AppBindRecord _binding, ActivityRecord _activity, IServiceConnection _conn, int _flags, int _clientLabel, PendingIntent _clientIntent)85     ConnectionRecord(AppBindRecord _binding, ActivityRecord _activity,
86                IServiceConnection _conn, int _flags,
87                int _clientLabel, PendingIntent _clientIntent) {
88         binding = _binding;
89         activity = _activity;
90         conn = _conn;
91         flags = _flags;
92         clientLabel = _clientLabel;
93         clientIntent = _clientIntent;
94     }
95 
toString()96     public String toString() {
97         if (stringName != null) {
98             return stringName;
99         }
100         StringBuilder sb = new StringBuilder(128);
101         sb.append("ConnectionRecord{");
102         sb.append(Integer.toHexString(System.identityHashCode(this)));
103         sb.append(" u");
104         sb.append(binding.client.userId);
105         sb.append(' ');
106         if ((flags&Context.BIND_AUTO_CREATE) != 0) {
107             sb.append("CR ");
108         }
109         if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
110             sb.append("DBG ");
111         }
112         if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
113             sb.append("!FG ");
114         }
115         if ((flags&Context.BIND_IMPORTANT_BACKGROUND) != 0) {
116             sb.append("IMPB ");
117         }
118         if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
119             sb.append("ABCLT ");
120         }
121         if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
122             sb.append("OOM ");
123         }
124         if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
125             sb.append("WPRI ");
126         }
127         if ((flags&Context.BIND_IMPORTANT) != 0) {
128             sb.append("IMP ");
129         }
130         if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
131             sb.append("WACT ");
132         }
133         if ((flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0) {
134             sb.append("FGSA ");
135         }
136         if ((flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
137             sb.append("FGS ");
138         }
139         if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
140             sb.append("LACT ");
141         }
142         if ((flags&Context.BIND_VISIBLE) != 0) {
143             sb.append("VIS ");
144         }
145         if ((flags&Context.BIND_SHOWING_UI) != 0) {
146             sb.append("UI ");
147         }
148         if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
149             sb.append("!VIS ");
150         }
151         if (serviceDead) {
152             sb.append("DEAD ");
153         }
154         sb.append(binding.service.shortName);
155         sb.append(":@");
156         sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
157         sb.append('}');
158         return stringName = sb.toString();
159     }
160 
writeToProto(ProtoOutputStream proto, long fieldId)161     public void writeToProto(ProtoOutputStream proto, long fieldId) {
162         if (binding == null) return; // if binding is null, don't write data, something is wrong.
163         long token = proto.start(fieldId);
164         proto.write(ConnectionRecordProto.HEX_HASH,
165                 Integer.toHexString(System.identityHashCode(this)));
166         if (binding.client != null) {
167             proto.write(ConnectionRecordProto.USER_ID, binding.client.userId);
168         }
169         ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, ConnectionRecordProto.FLAGS,
170                 flags, BIND_ORIG_ENUMS, BIND_PROTO_ENUMS);
171         if (serviceDead) {
172             proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
173         }
174         if (binding.service != null) {
175             proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortName);
176         }
177         proto.end(token);
178     }
179 }
180