1 /* 2 * Copyright (C) 2020 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.util.ArrayMap; 20 import android.util.TimeUtils; 21 22 import com.android.internal.annotations.GuardedBy; 23 24 import java.io.PrintWriter; 25 import java.util.ArrayList; 26 27 /** 28 * The state info of all content providers in the process. 29 */ 30 final class ProcessProviderRecord { 31 final ProcessRecord mApp; 32 private final ActivityManagerService mService; 33 34 /** 35 * The last time someone else was using a provider in this process. 36 */ 37 private long mLastProviderTime; 38 39 /** 40 * class (String) -> ContentProviderRecord. 41 */ 42 private final ArrayMap<String, ContentProviderRecord> mPubProviders = new ArrayMap<>(); 43 44 /** 45 * All ContentProviderRecord process is using. 46 */ 47 private final ArrayList<ContentProviderConnection> mConProviders = new ArrayList<>(); 48 getLastProviderTime()49 long getLastProviderTime() { 50 return mLastProviderTime; 51 } 52 setLastProviderTime(long lastProviderTime)53 void setLastProviderTime(long lastProviderTime) { 54 mLastProviderTime = lastProviderTime; 55 } 56 hasProvider(String name)57 boolean hasProvider(String name) { 58 return mPubProviders.containsKey(name); 59 } 60 getProvider(String name)61 ContentProviderRecord getProvider(String name) { 62 return mPubProviders.get(name); 63 } 64 numberOfProviders()65 int numberOfProviders() { 66 return mPubProviders.size(); 67 } 68 getProviderAt(int index)69 ContentProviderRecord getProviderAt(int index) { 70 return mPubProviders.valueAt(index); 71 } 72 installProvider(String name, ContentProviderRecord provider)73 void installProvider(String name, ContentProviderRecord provider) { 74 mPubProviders.put(name, provider); 75 } 76 removeProvider(String name)77 void removeProvider(String name) { 78 mPubProviders.remove(name); 79 } 80 ensureProviderCapacity(int capacity)81 void ensureProviderCapacity(int capacity) { 82 mPubProviders.ensureCapacity(capacity); 83 } 84 numberOfProviderConnections()85 int numberOfProviderConnections() { 86 return mConProviders.size(); 87 } 88 getProviderConnectionAt(int index)89 ContentProviderConnection getProviderConnectionAt(int index) { 90 return mConProviders.get(index); 91 } 92 addProviderConnection(ContentProviderConnection connection)93 void addProviderConnection(ContentProviderConnection connection) { 94 mConProviders.add(connection); 95 } 96 removeProviderConnection(ContentProviderConnection connection)97 boolean removeProviderConnection(ContentProviderConnection connection) { 98 return mConProviders.remove(connection); 99 } 100 ProcessProviderRecord(ProcessRecord app)101 ProcessProviderRecord(ProcessRecord app) { 102 mApp = app; 103 mService = app.mService; 104 } 105 106 /** 107 * @return Should the process restart or not. 108 */ 109 @GuardedBy("mService") onCleanupApplicationRecordLocked(boolean allowRestart)110 boolean onCleanupApplicationRecordLocked(boolean allowRestart) { 111 boolean restart = false; 112 // Remove published content providers. 113 for (int i = mPubProviders.size() - 1; i >= 0; i--) { 114 final ContentProviderRecord cpr = mPubProviders.valueAt(i); 115 if (cpr.proc != mApp) { 116 // If the hosting process record isn't really us, bail out 117 continue; 118 } 119 final boolean alwaysRemove = mApp.mErrorState.isBad() || !allowRestart; 120 final boolean inLaunching = mService.mCpHelper 121 .removeDyingProviderLocked(mApp, cpr, alwaysRemove); 122 if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) { 123 // We left the provider in the launching list, need to 124 // restart it. 125 restart = true; 126 } 127 128 cpr.provider = null; 129 cpr.setProcess(null); 130 } 131 mPubProviders.clear(); 132 133 // Take care of any launching providers waiting for this process. 134 if (mService.mCpHelper.cleanupAppInLaunchingProvidersLocked(mApp, false)) { 135 mService.mProcessList.noteProcessDiedLocked(mApp); 136 restart = true; 137 } 138 139 // Unregister from connected content providers. 140 if (!mConProviders.isEmpty()) { 141 for (int i = mConProviders.size() - 1; i >= 0; i--) { 142 final ContentProviderConnection conn = mConProviders.get(i); 143 conn.provider.connections.remove(conn); 144 mService.stopAssociationLocked(mApp.uid, mApp.processName, conn.provider.uid, 145 conn.provider.appInfo.longVersionCode, conn.provider.name, 146 conn.provider.info.processName); 147 } 148 mConProviders.clear(); 149 } 150 151 return restart; 152 } 153 dump(PrintWriter pw, String prefix, long nowUptime)154 void dump(PrintWriter pw, String prefix, long nowUptime) { 155 if (mLastProviderTime > 0) { 156 pw.print(prefix); pw.print("lastProviderTime="); 157 TimeUtils.formatDuration(mLastProviderTime, nowUptime, pw); 158 pw.println(); 159 } 160 if (mPubProviders.size() > 0) { 161 pw.print(prefix); pw.println("Published Providers:"); 162 for (int i = 0, size = mPubProviders.size(); i < size; i++) { 163 pw.print(prefix); pw.print(" - "); pw.println(mPubProviders.keyAt(i)); 164 pw.print(prefix); pw.print(" -> "); pw.println(mPubProviders.valueAt(i)); 165 } 166 } 167 if (mConProviders.size() > 0) { 168 pw.print(prefix); pw.println("Connected Providers:"); 169 for (int i = 0, size = mConProviders.size(); i < size; i++) { 170 pw.print(prefix); pw.print(" - "); 171 pw.println(mConProviders.get(i).toShortString()); 172 } 173 } 174 } 175 } 176