blob: 95c36ca8429efaaec460513ec247ffc9a42aed6a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 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.internal.os;
18
Michael Wachenschwanz55182462017-08-14 23:10:13 -070019import android.annotation.NonNull;
Artur Satayeved5a6ae2019-12-10 17:47:54 +000020import android.compat.annotation.UnsupportedAppUsage;
Olivier Gaillard289ba402018-07-24 18:50:13 +010021import android.os.Binder;
Michael Wachenschwanz55182462017-08-14 23:10:13 -070022import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.os.IBinder;
24import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.util.EventLog;
Michael Wachenschwanz55182462017-08-14 23:10:13 -070026import android.util.SparseIntArray;
27
28import com.android.internal.util.Preconditions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Hiroshi Yamauchidfefe2d2015-05-05 12:15:26 -070030import dalvik.system.VMRuntime;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import java.lang.ref.WeakReference;
Dianne Hackborn89ad4562014-08-24 16:45:38 -070033import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
35/**
36 * Private and debugging Binder APIs.
Olivier Gaillard289ba402018-07-24 18:50:13 +010037 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 * @see IBinder
39 */
40public class BinderInternal {
Michael Wachenschwanz55182462017-08-14 23:10:13 -070041 private static final String TAG = "BinderInternal";
Dianne Hackborn89ad4562014-08-24 16:45:38 -070042 static WeakReference<GcWatcher> sGcWatcher
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043 = new WeakReference<GcWatcher>(new GcWatcher());
Dianne Hackborn89ad4562014-08-24 16:45:38 -070044 static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
45 static Runnable[] sTmpWatchers = new Runnable[1];
46 static long sLastGcTime;
Michael Wachenschwanz55182462017-08-14 23:10:13 -070047 static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
48 new BinderProxyLimitListenerDelegate();
Dianne Hackborn89ad4562014-08-24 16:45:38 -070049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 static final class GcWatcher {
51 @Override
52 protected void finalize() throws Throwable {
53 handleGc();
Dianne Hackborn89ad4562014-08-24 16:45:38 -070054 sLastGcTime = SystemClock.uptimeMillis();
55 synchronized (sGcWatchers) {
56 sTmpWatchers = sGcWatchers.toArray(sTmpWatchers);
57 }
58 for (int i=0; i<sTmpWatchers.length; i++) {
59 if (sTmpWatchers[i] != null) {
60 sTmpWatchers[i].run();
61 }
62 }
63 sGcWatcher = new WeakReference<GcWatcher>(new GcWatcher());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 }
65 }
Dianne Hackborn89ad4562014-08-24 16:45:38 -070066
67 public static void addGcWatcher(Runnable watcher) {
68 synchronized (sGcWatchers) {
69 sGcWatchers.add(watcher);
70 }
71 }
72
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 /**
Olivier Gaillard289ba402018-07-24 18:50:13 +010074 * A session used by {@link Observer} in order to keep track of some data.
75 */
76 public static class CallSession {
77 // Binder interface descriptor.
Olivier Gaillard7a2a98b2018-07-26 13:29:16 +010078 public Class<? extends Binder> binderClass;
Olivier Gaillard289ba402018-07-24 18:50:13 +010079 // Binder transaction code.
80 public int transactionCode;
Olivier Gaillard289ba402018-07-24 18:50:13 +010081 // CPU time at the beginning of the call.
82 long cpuTimeStarted;
83 // System time at the beginning of the call.
84 long timeStarted;
85 // Should be set to one when an exception is thrown.
86 boolean exceptionThrown;
87 }
88
Olivier Gaillard76c231d2018-12-05 12:52:08 +000089
90 /**
91 * Responsible for resolving a work source.
92 */
93 @FunctionalInterface
94 public interface WorkSourceProvider {
95 /**
96 * <p>This method is called in a critical path of the binder transaction.
97 * <p>The implementation should never execute a binder call since it is called during a
98 * binder transaction.
99 *
Olivier Gaillardbab444a2019-01-30 17:11:40 +0000100 * @param untrustedWorkSourceUid The work source set by the caller.
Olivier Gaillard76c231d2018-12-05 12:52:08 +0000101 * @return the uid of the process to attribute the binder transaction to.
102 */
Olivier Gaillardbab444a2019-01-30 17:11:40 +0000103 int resolveWorkSourceUid(int untrustedWorkSourceUid);
Olivier Gaillard76c231d2018-12-05 12:52:08 +0000104 }
105
Olivier Gaillard289ba402018-07-24 18:50:13 +0100106 /**
107 * Allows to track various steps of an API call.
108 */
109 public interface Observer {
110 /**
111 * Called when a binder call starts.
112 *
113 * @return a CallSession to pass to the callEnded method.
114 */
Olivier Gaillard76c231d2018-12-05 12:52:08 +0000115 CallSession callStarted(Binder binder, int code, int workSourceUid);
Olivier Gaillard289ba402018-07-24 18:50:13 +0100116
117 /**
118 * Called when a binder call stops.
119 *
Olivier Gaillard0e4d61e2018-12-05 15:30:35 +0000120 * <li>This method will be called even when an exception is thrown by the binder stub
121 * implementation.
Olivier Gaillard289ba402018-07-24 18:50:13 +0100122 */
Olivier Gaillard76c231d2018-12-05 12:52:08 +0000123 void callEnded(CallSession s, int parcelRequestSize, int parcelReplySize,
124 int workSourceUid);
Olivier Gaillard289ba402018-07-24 18:50:13 +0100125
126 /**
127 * Called if an exception is thrown while executing the binder transaction.
128 *
129 * <li>BinderCallsStats#callEnded will be called afterwards.
130 * <li>Do not throw an exception in this method, it will swallow the original exception
131 * thrown by the binder transaction.
132 */
133 public void callThrewException(CallSession s, Exception exception);
134 }
135
136 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 * Add the calling thread to the IPC thread pool. This function does
138 * not return until the current process is exiting.
139 */
140 public static final native void joinThreadPool();
Olivier Gaillard289ba402018-07-24 18:50:13 +0100141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 /**
143 * Return the system time (as reported by {@link SystemClock#uptimeMillis
144 * SystemClock.uptimeMillis()}) that the last garbage collection occurred
145 * in this process. This is not for general application use, and the
146 * meaning of "when a garbage collection occurred" will change as the
147 * garbage collector evolves.
Olivier Gaillard289ba402018-07-24 18:50:13 +0100148 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 * @return Returns the time as per {@link SystemClock#uptimeMillis
150 * SystemClock.uptimeMillis()} of the last garbage collection.
151 */
152 public static long getLastGcTime() {
Dianne Hackborn89ad4562014-08-24 16:45:38 -0700153 return sLastGcTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 }
155
156 /**
157 * Return the global "context object" of the system. This is usually
158 * an implementation of IServiceManager, which you can use to find
159 * other services.
160 */
Andrei Onea15884392019-03-22 17:28:11 +0000161 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 public static final native IBinder getContextObject();
Olivier Gaillard289ba402018-07-24 18:50:13 +0100163
Dianne Hackborn887f3552009-12-07 17:59:37 -0800164 /**
165 * Special for system process to not allow incoming calls to run at
166 * background scheduling priority.
167 * @hide
168 */
169 public static final native void disableBackgroundScheduling(boolean disable);
Tim Murrayeef4a3d2016-04-19 14:14:20 -0700170
171 public static final native void setMaxThreads(int numThreads);
Olivier Gaillard289ba402018-07-24 18:50:13 +0100172
Andrei Onea15884392019-03-22 17:28:11 +0000173 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 static native final void handleGc();
Olivier Gaillard289ba402018-07-24 18:50:13 +0100175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 public static void forceGc(String reason) {
177 EventLog.writeEvent(2741, reason);
Hiroshi Yamauchidfefe2d2015-05-05 12:15:26 -0700178 VMRuntime.getRuntime().requestConcurrentGC();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 }
Olivier Gaillard289ba402018-07-24 18:50:13 +0100180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 static void forceBinderGc() {
182 forceGc("Binder");
183 }
Michael Wachenschwanz55182462017-08-14 23:10:13 -0700184
185 /**
186 * Enable/disable Binder Proxy Instance Counting by Uid. While enabled, the set callback will
187 * be called if this process holds too many Binder Proxies on behalf of a Uid.
188 * @param enabled true to enable counting, false to disable
189 */
190 public static final native void nSetBinderProxyCountEnabled(boolean enabled);
191
192 /**
193 * Get the current number of Binder Proxies held for each uid.
194 * @return SparseIntArray mapping uids to the number of Binder Proxies currently held
195 */
196 public static final native SparseIntArray nGetBinderProxyPerUidCounts();
197
198 /**
199 * Get the current number of Binder Proxies held for an individual uid.
200 * @param uid Requested uid for Binder Proxy count
201 * @return int with the number of Binder proxies held for a uid
202 */
203 public static final native int nGetBinderProxyCount(int uid);
204
205 /**
206 * Set the Binder Proxy watermarks. Default high watermark = 2500. Default low watermark = 2000
207 * @param high The limit at which the BinderProxyListener callback will be called.
208 * @param low The threshold a binder count must drop below before the callback
209 * can be called again. (This is to avoid many repeated calls to the
210 * callback in a brief period of time)
211 */
212 public static final native void nSetBinderProxyCountWatermarks(int high, int low);
213
214 /**
215 * Interface for callback invocation when the Binder Proxy limit is reached. onLimitReached will
216 * be called with the uid of the app causing too many Binder Proxies
217 */
218 public interface BinderProxyLimitListener {
219 public void onLimitReached(int uid);
220 }
221
222 /**
223 * Callback used by native code to trigger a callback in java code. The callback will be
224 * triggered when too many binder proxies from a uid hits the allowed limit.
225 * @param uid The uid of the bad behaving app sending too many binders
226 */
227 public static void binderProxyLimitCallbackFromNative(int uid) {
228 sBinderProxyLimitListenerDelegate.notifyClient(uid);
229 }
230
231 /**
232 * Set a callback to be triggered when a uid's Binder Proxy limit is reached for this process.
233 * @param listener OnLimitReached of listener will be called in the thread provided by handler
234 * @param handler must not be null, callback will be posted through the handler;
235 *
236 */
237 public static void setBinderProxyCountCallback(BinderProxyLimitListener listener,
238 @NonNull Handler handler) {
239 Preconditions.checkNotNull(handler,
240 "Must provide NonNull Handler to setBinderProxyCountCallback when setting "
241 + "BinderProxyLimitListener");
242 sBinderProxyLimitListenerDelegate.setListener(listener, handler);
243 }
244
245 /**
246 * Clear the Binder Proxy callback
247 */
248 public static void clearBinderProxyCountCallback() {
249 sBinderProxyLimitListenerDelegate.setListener(null, null);
250 }
251
252 static private class BinderProxyLimitListenerDelegate {
253 private BinderProxyLimitListener mBinderProxyLimitListener;
254 private Handler mHandler;
255
256 void setListener(BinderProxyLimitListener listener, Handler handler) {
257 synchronized (this) {
258 mBinderProxyLimitListener = listener;
259 mHandler = handler;
260 }
261 }
262
263 void notifyClient(final int uid) {
264 synchronized (this) {
265 if (mBinderProxyLimitListener != null) {
266 mHandler.post(new Runnable() {
267 @Override
268 public void run() {
269 mBinderProxyLimitListener.onLimitReached(uid);
270 }
271 });
272 }
273 }
274 }
275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276}