blob: f338cfcb773714906d57200839882476480fbacb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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.app.IActivityManager.ContentProviderHolder;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070020import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.content.pm.ApplicationInfo;
22import android.content.pm.ProviderInfo;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080023import android.os.IBinder;
24import android.os.IBinder.DeathRecipient;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.Process;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080026import android.os.RemoteException;
27import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
29import java.io.PrintWriter;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080030import java.util.HashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import java.util.HashSet;
32
33class ContentProviderRecord extends ContentProviderHolder {
34 // All attached clients
35 final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>();
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080036 // Handles for non-framework processes supported by this provider
37 HashMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
38 // Count for external process for which we have no handles.
39 int externalProcessNoHandleCount;
40 final ActivityManagerService service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 final int uid;
42 final ApplicationInfo appInfo;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070043 final ComponentName name;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070044 ProcessRecord proc; // if non-null, hosting process.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045 ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070046 String stringName;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080047
48 public ContentProviderRecord(ActivityManagerService _service, ProviderInfo _info,
49 ApplicationInfo ai, ComponentName _name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 super(_info);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080051 service = _service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 uid = ai.uid;
53 appInfo = ai;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070054 name = _name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID;
56 }
57
58 public ContentProviderRecord(ContentProviderRecord cpr) {
59 super(cpr.info);
60 uid = cpr.uid;
61 appInfo = cpr.appInfo;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070062 name = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 noReleaseNeeded = cpr.noReleaseNeeded;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080064 service = cpr.service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 }
66
67 public boolean canRunHere(ProcessRecord app) {
68 return (info.multiprocess || info.processName.equals(app.processName))
69 && (uid == Process.SYSTEM_UID || uid == app.info.uid);
70 }
71
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080072 public void addExternalProcessHandleLocked(IBinder token) {
73 if (token == null) {
74 externalProcessNoHandleCount++;
75 } else {
76 if (externalProcessTokenToHandle == null) {
77 externalProcessTokenToHandle = new HashMap<IBinder, ExternalProcessHandle>();
78 }
79 ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
80 if (handle == null) {
81 handle = new ExternalProcessHandle(token);
82 externalProcessTokenToHandle.put(token, handle);
83 }
84 handle.mAcquisitionCount++;
85 }
86 }
87
88 public boolean removeExternalProcessHandleLocked(IBinder token) {
89 if (hasExternalProcessHandles()) {
90 boolean hasHandle = false;
91 if (externalProcessTokenToHandle != null) {
92 ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
93 if (handle != null) {
94 hasHandle = true;
95 handle.mAcquisitionCount--;
96 if (handle.mAcquisitionCount == 0) {
97 removeExternalProcessHandleInternalLocked(token);
98 return true;
99 }
100 }
101 }
102 if (!hasHandle) {
103 externalProcessNoHandleCount--;
104 return true;
105 }
106 }
107 return false;
108 }
109
110 private void removeExternalProcessHandleInternalLocked(IBinder token) {
111 ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
112 handle.unlinkFromOwnDeathLocked();
113 externalProcessTokenToHandle.remove(token);
114 if (externalProcessTokenToHandle.size() == 0) {
115 externalProcessTokenToHandle = null;
116 }
117 }
118
119 public boolean hasExternalProcessHandles() {
120 return (externalProcessTokenToHandle != null || externalProcessNoHandleCount > 0);
121 }
122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700124 pw.print(prefix); pw.print("package=");
125 pw.print(info.applicationInfo.packageName);
Dianne Hackborne17aeb32011-04-07 15:11:57 -0700126 pw.print(" process="); pw.println(info.processName);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -0700127 pw.print(prefix); pw.print("proc="); pw.println(proc);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700128 if (launchingApp != null) {
129 pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp);
130 }
131 pw.print(prefix); pw.print("uid="); pw.print(uid);
132 pw.print(" provider="); pw.println(provider);
133 pw.print(prefix); pw.print("name="); pw.println(info.authority);
134 if (info.isSyncable || info.multiprocess || info.initOrder != 0) {
135 pw.print(prefix); pw.print("isSyncable="); pw.print(info.isSyncable);
136 pw.print("multiprocess="); pw.print(info.multiprocess);
137 pw.print(" initOrder="); pw.println(info.initOrder);
138 }
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800139 if (hasExternalProcessHandles()) {
140 pw.print(prefix); pw.print("externals=");
141 pw.println(externalProcessTokenToHandle.size());
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -0800142 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700143 if (clients.size() > 0) {
Dianne Hackborn8ec8d412011-11-14 18:27:24 -0800144 pw.print(prefix); pw.println("Clients:");
145 for (ProcessRecord cproc : clients) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -0800146 pw.print(prefix); pw.print(" - "); pw.println(cproc.toShortString());
Dianne Hackborn8ec8d412011-11-14 18:27:24 -0800147 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 }
150
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800151 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700153 if (stringName != null) {
154 return stringName;
155 }
156 StringBuilder sb = new StringBuilder(128);
157 sb.append("ContentProviderRecord{");
158 sb.append(Integer.toHexString(System.identityHashCode(this)));
159 sb.append(' ');
160 sb.append(info.name);
161 sb.append('}');
162 return stringName = sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 }
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800164
165 // This class represents a handle from an external process to a provider.
166 private class ExternalProcessHandle implements DeathRecipient {
167 private static final String LOG_TAG = "ExternalProcessHanldle";
168
169 private final IBinder mToken;
170 private int mAcquisitionCount;
171
172 public ExternalProcessHandle(IBinder token) {
173 mToken = token;
174 try {
175 token.linkToDeath(this, 0);
176 } catch (RemoteException re) {
177 Slog.e(LOG_TAG, "Couldn't register for death for token: " + mToken, re);
178 }
179 }
180
181 public void unlinkFromOwnDeathLocked() {
182 mToken.unlinkToDeath(this, 0);
183 }
184
185 @Override
186 public void binderDied() {
187 synchronized (service) {
188 if (hasExternalProcessHandles() &&
189 externalProcessTokenToHandle.get(mToken) != null) {
190 removeExternalProcessHandleInternalLocked(mToken);
191 }
192 }
193 }
194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195}