blob: e97ebd7eee06ce98949800eca9264e0dd4ffc57d [file] [log] [blame]
Alan Viverette3da604b2020-06-10 18:34:39 +00001/*
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 android.app;
18
19import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
20import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
21import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
22import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
23import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
24import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
25import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
26import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
27import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
28import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
29import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
30import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
31import static android.view.Display.INVALID_DISPLAY;
32
33import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
34
35import android.annotation.NonNull;
36import android.annotation.Nullable;
37import android.app.assist.AssistContent;
38import android.app.assist.AssistStructure;
39import android.app.backup.BackupAgent;
40import android.app.servertransaction.ActivityLifecycleItem;
41import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
42import android.app.servertransaction.ActivityRelaunchItem;
43import android.app.servertransaction.ActivityResultItem;
44import android.app.servertransaction.ClientTransaction;
45import android.app.servertransaction.ClientTransactionItem;
46import android.app.servertransaction.PauseActivityItem;
47import android.app.servertransaction.PendingTransactionActions;
48import android.app.servertransaction.PendingTransactionActions.StopInfo;
49import android.app.servertransaction.ResumeActivityItem;
50import android.app.servertransaction.TransactionExecutor;
51import android.app.servertransaction.TransactionExecutorHelper;
52import android.compat.annotation.UnsupportedAppUsage;
53import android.content.AutofillOptions;
54import android.content.BroadcastReceiver;
55import android.content.ComponentCallbacks2;
56import android.content.ComponentName;
57import android.content.ContentCaptureOptions;
58import android.content.ContentProvider;
59import android.content.ContentResolver;
60import android.content.Context;
61import android.content.IContentProvider;
62import android.content.IIntentReceiver;
63import android.content.Intent;
64import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.IPackageManager;
67import android.content.pm.InstrumentationInfo;
68import android.content.pm.PackageInfo;
69import android.content.pm.PackageManager;
70import android.content.pm.PackageManager.NameNotFoundException;
71import android.content.pm.ParceledListSlice;
72import android.content.pm.ProviderInfo;
73import android.content.pm.ProviderInfoList;
74import android.content.pm.ServiceInfo;
75import android.content.res.AssetManager;
76import android.content.res.CompatibilityInfo;
77import android.content.res.Configuration;
78import android.content.res.Resources;
79import android.content.res.Resources.Theme;
80import android.content.res.loader.ResourcesLoader;
81import android.database.sqlite.SQLiteDatabase;
82import android.database.sqlite.SQLiteDebug;
83import android.database.sqlite.SQLiteDebug.DbStats;
84import android.graphics.Bitmap;
85import android.graphics.Canvas;
86import android.graphics.HardwareRenderer;
87import android.graphics.ImageDecoder;
88import android.hardware.display.DisplayManagerGlobal;
89import android.inputmethodservice.InputMethodService;
90import android.net.ConnectivityManager;
91import android.net.IConnectivityManager;
92import android.net.Proxy;
93import android.net.Uri;
94import android.os.AsyncTask;
95import android.os.Binder;
96import android.os.Build;
97import android.os.Bundle;
98import android.os.CancellationSignal;
99import android.os.Debug;
100import android.os.Environment;
101import android.os.FileUtils;
102import android.os.GraphicsEnvironment;
103import android.os.Handler;
104import android.os.HandlerExecutor;
105import android.os.IBinder;
106import android.os.ICancellationSignal;
107import android.os.LocaleList;
108import android.os.Looper;
109import android.os.Message;
110import android.os.MessageQueue;
111import android.os.Parcel;
112import android.os.ParcelFileDescriptor;
113import android.os.PersistableBundle;
114import android.os.Process;
115import android.os.RemoteCallback;
116import android.os.RemoteException;
117import android.os.ServiceManager;
118import android.os.StatsFrameworkInitializer;
119import android.os.StatsServiceManager;
120import android.os.StrictMode;
121import android.os.SystemClock;
122import android.os.SystemProperties;
123import android.os.TelephonyServiceManager;
124import android.os.Trace;
125import android.os.UserHandle;
126import android.permission.IPermissionManager;
127import android.provider.BlockedNumberContract;
128import android.provider.CalendarContract;
129import android.provider.CallLog;
130import android.provider.ContactsContract;
131import android.provider.Downloads;
132import android.provider.FontsContract;
133import android.provider.Settings;
134import android.renderscript.RenderScriptCacheDir;
135import android.security.NetworkSecurityPolicy;
136import android.security.net.config.NetworkSecurityConfigProvider;
137import android.system.ErrnoException;
138import android.system.OsConstants;
139import android.system.StructStat;
140import android.telephony.TelephonyFrameworkInitializer;
141import android.util.AndroidRuntimeException;
142import android.util.ArrayMap;
143import android.util.DisplayMetrics;
144import android.util.EventLog;
145import android.util.Log;
146import android.util.LogPrinter;
147import android.util.MergedConfiguration;
148import android.util.Pair;
149import android.util.PrintWriterPrinter;
150import android.util.Slog;
151import android.util.SparseArray;
152import android.util.SparseIntArray;
153import android.util.SuperNotCalledException;
154import android.util.UtilConfig;
155import android.util.proto.ProtoOutputStream;
156import android.view.Choreographer;
157import android.view.ContextThemeWrapper;
158import android.view.Display;
159import android.view.ThreadedRenderer;
160import android.view.View;
161import android.view.ViewDebug;
162import android.view.ViewManager;
163import android.view.ViewRootImpl;
164import android.view.Window;
165import android.view.WindowManager;
166import android.view.WindowManagerGlobal;
167import android.webkit.WebView;
168
169import com.android.internal.annotations.GuardedBy;
170import com.android.internal.annotations.VisibleForTesting;
171import com.android.internal.app.IVoiceInteractor;
172import com.android.internal.content.ReferrerIntent;
173import com.android.internal.os.BinderInternal;
174import com.android.internal.os.RuntimeInit;
175import com.android.internal.os.SomeArgs;
176import com.android.internal.util.ArrayUtils;
177import com.android.internal.util.FastPrintWriter;
178import com.android.internal.util.Preconditions;
179import com.android.internal.util.function.pooled.PooledLambda;
180import com.android.org.conscrypt.OpenSSLSocketImpl;
181import com.android.org.conscrypt.TrustedCertificateStore;
182import com.android.server.am.MemInfoDumpProto;
183
184import dalvik.system.CloseGuard;
185import dalvik.system.VMDebug;
186import dalvik.system.VMRuntime;
187
188import libcore.io.ForwardingOs;
189import libcore.io.IoUtils;
190import libcore.io.Os;
191import libcore.net.event.NetworkEventDispatcher;
192
193import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
194
195import java.io.File;
196import java.io.FileDescriptor;
197import java.io.FileNotFoundException;
198import java.io.FileOutputStream;
199import java.io.IOException;
200import java.io.PrintWriter;
201import java.lang.ref.WeakReference;
202import java.lang.reflect.Method;
203import java.net.InetAddress;
204import java.nio.file.Files;
205import java.nio.file.Path;
206import java.nio.file.StandardCopyOption;
207import java.text.DateFormat;
208import java.util.ArrayList;
209import java.util.Arrays;
210import java.util.Collections;
211import java.util.List;
212import java.util.Locale;
213import java.util.Map;
214import java.util.Objects;
215import java.util.TimeZone;
216import java.util.concurrent.Executor;
217import java.util.concurrent.atomic.AtomicInteger;
218
219final class RemoteServiceException extends AndroidRuntimeException {
220 public RemoteServiceException(String msg) {
221 super(msg);
222 }
223}
224
225/**
226 * This manages the execution of the main thread in an
227 * application process, scheduling and executing activities,
228 * broadcasts, and other operations on it as the activity
229 * manager requests.
230 *
231 * {@hide}
232 */
233public final class ActivityThread extends ClientTransactionHandler {
234 /** @hide */
235 public static final String TAG = "ActivityThread";
236 private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
237 static final boolean localLOGV = false;
238 static final boolean DEBUG_MESSAGES = false;
239 /** @hide */
240 public static final boolean DEBUG_BROADCAST = false;
241 private static final boolean DEBUG_RESULTS = false;
242 private static final boolean DEBUG_BACKUP = false;
243 public static final boolean DEBUG_CONFIGURATION = false;
244 private static final boolean DEBUG_SERVICE = false;
245 public static final boolean DEBUG_MEMORY_TRIM = false;
246 private static final boolean DEBUG_PROVIDER = false;
247 public static final boolean DEBUG_ORDER = false;
248 private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
249 /**
250 * If the activity doesn't become idle in time, the timeout will ensure to apply the pending top
251 * process state.
252 */
253 private static final long PENDING_TOP_PROCESS_STATE_TIMEOUT = 1000;
254 /**
255 * The delay to release the provider when it has no more references. It reduces the number of
256 * transactions for acquiring and releasing provider if the client accesses the provider
257 * frequently in a short time.
258 */
259 private static final long CONTENT_PROVIDER_RETAIN_TIME = 1000;
260 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
261
262 /** Type for IActivityManager.serviceDoneExecuting: anonymous operation */
263 public static final int SERVICE_DONE_EXECUTING_ANON = 0;
264 /** Type for IActivityManager.serviceDoneExecuting: done with an onStart call */
265 public static final int SERVICE_DONE_EXECUTING_START = 1;
266 /** Type for IActivityManager.serviceDoneExecuting: done stopping (destroying) service */
267 public static final int SERVICE_DONE_EXECUTING_STOP = 2;
268
269 // Whether to invoke an activity callback after delivering new configuration.
270 private static final boolean REPORT_TO_ACTIVITY = true;
271
272 /** Use foreground GC policy (less pause time) and higher JIT weight. */
273 private static final int VM_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
274 /** Use background GC policy and default JIT threshold. */
275 private static final int VM_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
276
277 /**
278 * Denotes an invalid sequence number corresponding to a process state change.
279 */
280 public static final long INVALID_PROC_STATE_SEQ = -1;
281
282 /**
283 * Identifier for the sequence no. associated with this process start. It will be provided
284 * as one of the arguments when the process starts.
285 */
286 public static final String PROC_START_SEQ_IDENT = "seq=";
287
288 private final Object mNetworkPolicyLock = new Object();
289
290 /**
291 * Denotes the sequence number of the process state change for which the main thread needs
292 * to block until the network rules are updated for it.
293 *
294 * Value of {@link #INVALID_PROC_STATE_SEQ} indicates there is no need for blocking.
295 */
296 @GuardedBy("mNetworkPolicyLock")
297 private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
298
299 @UnsupportedAppUsage
300 private ContextImpl mSystemContext;
301 private ContextImpl mSystemUiContext;
302
303 @UnsupportedAppUsage
304 static volatile IPackageManager sPackageManager;
305 private static volatile IPermissionManager sPermissionManager;
306
307 @UnsupportedAppUsage
308 final ApplicationThread mAppThread = new ApplicationThread();
309 @UnsupportedAppUsage
310 final Looper mLooper = Looper.myLooper();
311 @UnsupportedAppUsage
312 final H mH = new H();
313 final Executor mExecutor = new HandlerExecutor(mH);
314 /**
315 * Maps from activity token to local record of running activities in this process.
316 *
317 * This variable is readable if the code is running in activity thread or holding {@link
318 * #mResourcesManager}. It's only writable if the code is running in activity thread and holding
319 * {@link #mResourcesManager}.
320 */
321 @UnsupportedAppUsage
322 final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
323 /** The activities to be truly destroyed (not include relaunch). */
324 final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed =
325 Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>());
326 // List of new activities (via ActivityRecord.nextIdle) that should
327 // be reported when next we idle.
328 ActivityClientRecord mNewActivities = null;
329 // Number of activities that are currently visible on-screen.
330 @UnsupportedAppUsage
331 int mNumVisibleActivities = 0;
332 private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
333 @GuardedBy("mAppThread")
334 private int mLastProcessState = PROCESS_STATE_UNKNOWN;
335 @GuardedBy("mAppThread")
336 private int mPendingProcessState = PROCESS_STATE_UNKNOWN;
337 ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
338 private int mLastSessionId;
339 @UnsupportedAppUsage
340 final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
341 @UnsupportedAppUsage
342 AppBindData mBoundApplication;
343 Profiler mProfiler;
344 @UnsupportedAppUsage
345 int mCurDefaultDisplayDpi;
346 @UnsupportedAppUsage
347 boolean mDensityCompatMode;
348 @UnsupportedAppUsage
349 Configuration mConfiguration;
350 Configuration mCompatConfiguration;
351 @UnsupportedAppUsage
352 Application mInitialApplication;
353 @UnsupportedAppUsage
354 final ArrayList<Application> mAllApplications
355 = new ArrayList<Application>();
356 /**
357 * Bookkeeping of instantiated backup agents indexed first by user id, then by package name.
358 * Indexing by user id supports parallel backups across users on system packages as they run in
359 * the same process with the same package name. Indexing by package name supports multiple
360 * distinct applications running in the same process.
361 */
362 private final SparseArray<ArrayMap<String, BackupAgent>> mBackupAgentsByUser =
363 new SparseArray<>();
364 /** Reference to singleton {@link ActivityThread} */
365 @UnsupportedAppUsage
366 private static volatile ActivityThread sCurrentActivityThread;
367 @UnsupportedAppUsage
368 Instrumentation mInstrumentation;
369 String mInstrumentationPackageName = null;
370 @UnsupportedAppUsage
371 String mInstrumentationAppDir = null;
372 String[] mInstrumentationSplitAppDirs = null;
373 String mInstrumentationLibDir = null;
374 @UnsupportedAppUsage
375 String mInstrumentedAppDir = null;
376 String[] mInstrumentedSplitAppDirs = null;
377 String mInstrumentedLibDir = null;
378 boolean mSystemThread = false;
379 boolean mSomeActivitiesChanged = false;
380 /* package */ boolean mHiddenApiWarningShown = false;
381
382 // These can be accessed by multiple threads; mResourcesManager is the lock.
383 // XXX For now we keep around information about all packages we have
384 // seen, not removing entries from this map.
385 // NOTE: The activity and window managers need to call in to
386 // ActivityThread to do things like update resource configurations,
387 // which means this lock gets held while the activity and window managers
388 // holds their own lock. Thus you MUST NEVER call back into the activity manager
389 // or window manager or anything that depends on them while holding this lock.
390 // These LoadedApk are only valid for the userId that we're running as.
391 @GuardedBy("mResourcesManager")
392 @UnsupportedAppUsage
393 final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>();
394 @GuardedBy("mResourcesManager")
395 @UnsupportedAppUsage
396 final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>();
397 @GuardedBy("mResourcesManager")
398 final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>();
399 @GuardedBy("mResourcesManager")
400 @UnsupportedAppUsage
401 Configuration mPendingConfiguration = null;
402 // An executor that performs multi-step transactions.
403 private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
404
405 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
406 private final ResourcesManager mResourcesManager;
407
408 // Registry of remote cancellation transports pending a reply with reply handles.
409 @GuardedBy("this")
410 private @Nullable Map<SafeCancellationTransport, CancellationSignal> mRemoteCancellations;
411
412 private final Map<IBinder, Integer> mLastReportedWindowingMode = Collections.synchronizedMap(
413 new ArrayMap<>());
414
415 private static final class ProviderKey {
416 final String authority;
417 final int userId;
418
419 public ProviderKey(String authority, int userId) {
420 this.authority = authority;
421 this.userId = userId;
422 }
423
424 @Override
425 public boolean equals(Object o) {
426 if (o instanceof ProviderKey) {
427 final ProviderKey other = (ProviderKey) o;
428 return Objects.equals(authority, other.authority) && userId == other.userId;
429 }
430 return false;
431 }
432
433 @Override
434 public int hashCode() {
435 return ((authority != null) ? authority.hashCode() : 0) ^ userId;
436 }
437 }
438
439 // The lock of mProviderMap protects the following variables.
440 @UnsupportedAppUsage
441 final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
442 = new ArrayMap<ProviderKey, ProviderClientRecord>();
443 @UnsupportedAppUsage
444 final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
445 = new ArrayMap<IBinder, ProviderRefCount>();
446 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
447 final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
448 = new ArrayMap<IBinder, ProviderClientRecord>();
449 @UnsupportedAppUsage
450 final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
451 = new ArrayMap<ComponentName, ProviderClientRecord>();
452
453 // Mitigation for b/74523247: Used to serialize calls to AM.getContentProvider().
454 // Note we never removes items from this map but that's okay because there are only so many
455 // users and so many authorities.
456 // TODO Remove it once we move CPR.wait() from AMS to the client side.
457 @GuardedBy("mGetProviderLocks")
458 final ArrayMap<ProviderKey, Object> mGetProviderLocks = new ArrayMap<>();
459
460 final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
461 = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
462
463 final GcIdler mGcIdler = new GcIdler();
464 final PurgeIdler mPurgeIdler = new PurgeIdler();
465
466 boolean mPurgeIdlerScheduled = false;
467 boolean mGcIdlerScheduled = false;
468
469 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
470 static volatile Handler sMainThreadHandler; // set once in main()
471
472 Bundle mCoreSettings = null;
473
474 boolean mHasImeComponent = false;
475
476 /** Activity client record, used for bookkeeping for the real {@link Activity} instance. */
477 public static final class ActivityClientRecord {
478 @UnsupportedAppUsage
479 public IBinder token;
480 public IBinder assistToken;
481 int ident;
482 @UnsupportedAppUsage
483 Intent intent;
484 String referrer;
485 IVoiceInteractor voiceInteractor;
486 Bundle state;
487 PersistableBundle persistentState;
488 @UnsupportedAppUsage
489 Activity activity;
490 Window window;
491 Activity parent;
492 String embeddedID;
493 Activity.NonConfigurationInstances lastNonConfigurationInstances;
494 // TODO(lifecycler): Use mLifecycleState instead.
495 @UnsupportedAppUsage
496 boolean paused;
497 @UnsupportedAppUsage
498 boolean stopped;
499 boolean hideForNow;
500 Configuration newConfig;
501 Configuration createdConfig;
502 Configuration overrideConfig;
503 // Used to save the last reported configuration from server side so that activity
504 // configuration transactions can always use the latest configuration.
505 @GuardedBy("this")
506 private Configuration mPendingOverrideConfig;
507 // Used for consolidating configs before sending on to Activity.
508 private Configuration tmpConfig = new Configuration();
509 // Callback used for updating activity override config.
510 ViewRootImpl.ActivityConfigCallback configCallback;
511 ActivityClientRecord nextIdle;
512
513 // Indicates whether this activity is currently the topmost resumed one in the system.
514 // This holds the last reported value from server.
515 boolean isTopResumedActivity;
516 // This holds the value last sent to the activity. This is needed, because an update from
517 // server may come at random time, but we always need to report changes between ON_RESUME
518 // and ON_PAUSE to the app.
519 boolean lastReportedTopResumedState;
520
521 ProfilerInfo profilerInfo;
522
523 @UnsupportedAppUsage
524 ActivityInfo activityInfo;
525 @UnsupportedAppUsage
526 CompatibilityInfo compatInfo;
527 @UnsupportedAppUsage
528 public LoadedApk packageInfo;
529
530 List<ResultInfo> pendingResults;
531 List<ReferrerIntent> pendingIntents;
532
533 boolean startsNotResumed;
534 public final boolean isForward;
535 int pendingConfigChanges;
536 // Whether we are in the process of performing on user leaving.
537 boolean mIsUserLeaving;
538
539 Window mPendingRemoveWindow;
540 WindowManager mPendingRemoveWindowManager;
541 @UnsupportedAppUsage
542 boolean mPreserveWindow;
543
544 @LifecycleState
545 private int mLifecycleState = PRE_ON_CREATE;
546
547 @VisibleForTesting
548 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
549 public ActivityClientRecord() {
550 this.isForward = false;
551 init();
552 }
553
554 public ActivityClientRecord(IBinder token, Intent intent, int ident,
555 ActivityInfo info, Configuration overrideConfig, CompatibilityInfo compatInfo,
556 String referrer, IVoiceInteractor voiceInteractor, Bundle state,
557 PersistableBundle persistentState, List<ResultInfo> pendingResults,
558 List<ReferrerIntent> pendingNewIntents, boolean isForward,
559 ProfilerInfo profilerInfo, ClientTransactionHandler client,
560 IBinder assistToken) {
561 this.token = token;
562 this.assistToken = assistToken;
563 this.ident = ident;
564 this.intent = intent;
565 this.referrer = referrer;
566 this.voiceInteractor = voiceInteractor;
567 this.activityInfo = info;
568 this.compatInfo = compatInfo;
569 this.state = state;
570 this.persistentState = persistentState;
571 this.pendingResults = pendingResults;
572 this.pendingIntents = pendingNewIntents;
573 this.isForward = isForward;
574 this.profilerInfo = profilerInfo;
575 this.overrideConfig = overrideConfig;
576 this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo,
577 compatInfo);
578 init();
579 }
580
581 /** Common initializer for all constructors. */
582 private void init() {
583 parent = null;
584 embeddedID = null;
585 paused = false;
586 stopped = false;
587 hideForNow = false;
588 nextIdle = null;
589 configCallback = (Configuration overrideConfig, int newDisplayId) -> {
590 if (activity == null) {
591 throw new IllegalStateException(
592 "Received config update for non-existing activity");
593 }
594 // Given alwaysReportChange=false because the configuration is from view root, the
595 // activity may not be able to handle the changes. In that case the activity will be
596 // relaunched immediately, then Activity#onConfigurationChanged shouldn't be called.
597 activity.mMainThread.handleActivityConfigurationChanged(token, overrideConfig,
598 newDisplayId, false /* alwaysReportChange */);
599 };
600 }
601
602 /** Get the current lifecycle state. */
603 public int getLifecycleState() {
604 return mLifecycleState;
605 }
606
607 /** Update the current lifecycle state for internal bookkeeping. */
608 public void setState(@LifecycleState int newLifecycleState) {
609 mLifecycleState = newLifecycleState;
610 switch (mLifecycleState) {
611 case ON_CREATE:
612 paused = true;
613 stopped = true;
614 break;
615 case ON_START:
616 paused = true;
617 stopped = false;
618 break;
619 case ON_RESUME:
620 paused = false;
621 stopped = false;
622 break;
623 case ON_PAUSE:
624 paused = true;
625 stopped = false;
626 break;
627 case ON_STOP:
628 paused = true;
629 stopped = true;
630 break;
631 }
632 }
633
634 private boolean isPreHoneycomb() {
635 return activity != null && activity.getApplicationInfo().targetSdkVersion
636 < android.os.Build.VERSION_CODES.HONEYCOMB;
637 }
638
639 private boolean isPreP() {
640 return activity != null && activity.getApplicationInfo().targetSdkVersion
641 < android.os.Build.VERSION_CODES.P;
642 }
643
644 public boolean isPersistable() {
645 return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS;
646 }
647
648 public boolean isVisibleFromServer() {
649 return activity != null && activity.mVisibleFromServer;
650 }
651
652 public String toString() {
653 ComponentName componentName = intent != null ? intent.getComponent() : null;
654 return "ActivityRecord{"
655 + Integer.toHexString(System.identityHashCode(this))
656 + " token=" + token + " " + (componentName == null
657 ? "no component name" : componentName.toShortString())
658 + "}";
659 }
660
661 public String getStateString() {
662 StringBuilder sb = new StringBuilder();
663 sb.append("ActivityClientRecord{");
664 sb.append("paused=").append(paused);
665 sb.append(", stopped=").append(stopped);
666 sb.append(", hideForNow=").append(hideForNow);
667 sb.append(", startsNotResumed=").append(startsNotResumed);
668 sb.append(", isForward=").append(isForward);
669 sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
670 sb.append(", preserveWindow=").append(mPreserveWindow);
671 if (activity != null) {
672 sb.append(", Activity{");
673 sb.append("resumed=").append(activity.mResumed);
674 sb.append(", stopped=").append(activity.mStopped);
675 sb.append(", finished=").append(activity.isFinishing());
676 sb.append(", destroyed=").append(activity.isDestroyed());
677 sb.append(", startedActivity=").append(activity.mStartedActivity);
678 sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
679 sb.append("}");
680 }
681 sb.append("}");
682 return sb.toString();
683 }
684 }
685
686 final class ProviderClientRecord {
687 final String[] mNames;
688 @UnsupportedAppUsage
689 final IContentProvider mProvider;
690 @UnsupportedAppUsage
691 final ContentProvider mLocalProvider;
692 @UnsupportedAppUsage
693 final ContentProviderHolder mHolder;
694
695 ProviderClientRecord(String[] names, IContentProvider provider,
696 ContentProvider localProvider, ContentProviderHolder holder) {
697 mNames = names;
698 mProvider = provider;
699 mLocalProvider = localProvider;
700 mHolder = holder;
701 }
702 }
703
704 static final class ReceiverData extends BroadcastReceiver.PendingResult {
705 public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
706 boolean ordered, boolean sticky, IBinder token, int sendingUser) {
707 super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
708 token, sendingUser, intent.getFlags());
709 this.intent = intent;
710 }
711
712 @UnsupportedAppUsage
713 Intent intent;
714 @UnsupportedAppUsage
715 ActivityInfo info;
716 @UnsupportedAppUsage
717 CompatibilityInfo compatInfo;
718 public String toString() {
719 return "ReceiverData{intent=" + intent + " packageName=" +
720 info.packageName + " resultCode=" + getResultCode()
721 + " resultData=" + getResultData() + " resultExtras="
722 + getResultExtras(false) + "}";
723 }
724 }
725
726 static final class CreateBackupAgentData {
727 ApplicationInfo appInfo;
728 CompatibilityInfo compatInfo;
729 int backupMode;
730 int userId;
731 public String toString() {
732 return "CreateBackupAgentData{appInfo=" + appInfo
733 + " backupAgent=" + appInfo.backupAgentName
734 + " mode=" + backupMode + " userId=" + userId + "}";
735 }
736 }
737
738 static final class CreateServiceData {
739 @UnsupportedAppUsage
740 CreateServiceData() {
741 }
742 @UnsupportedAppUsage
743 IBinder token;
744 @UnsupportedAppUsage
745 ServiceInfo info;
746 @UnsupportedAppUsage
747 CompatibilityInfo compatInfo;
748 @UnsupportedAppUsage
749 Intent intent;
750 public String toString() {
751 return "CreateServiceData{token=" + token + " className="
752 + info.name + " packageName=" + info.packageName
753 + " intent=" + intent + "}";
754 }
755 }
756
757 static final class BindServiceData {
758 @UnsupportedAppUsage
759 IBinder token;
760 @UnsupportedAppUsage
761 Intent intent;
762 boolean rebind;
763 public String toString() {
764 return "BindServiceData{token=" + token + " intent=" + intent + "}";
765 }
766 }
767
768 static final class ServiceArgsData {
769 @UnsupportedAppUsage
770 IBinder token;
771 boolean taskRemoved;
772 int startId;
773 int flags;
774 @UnsupportedAppUsage
775 Intent args;
776 public String toString() {
777 return "ServiceArgsData{token=" + token + " startId=" + startId
778 + " args=" + args + "}";
779 }
780 }
781
782 static final class AppBindData {
783 @UnsupportedAppUsage
784 AppBindData() {
785 }
786 @UnsupportedAppUsage
787 LoadedApk info;
788 @UnsupportedAppUsage
789 String processName;
790 @UnsupportedAppUsage
791 ApplicationInfo appInfo;
792 @UnsupportedAppUsage
793 List<ProviderInfo> providers;
794 ComponentName instrumentationName;
795 @UnsupportedAppUsage
796 Bundle instrumentationArgs;
797 IInstrumentationWatcher instrumentationWatcher;
798 IUiAutomationConnection instrumentationUiAutomationConnection;
799 int debugMode;
800 boolean enableBinderTracking;
801 boolean trackAllocation;
802 @UnsupportedAppUsage
803 boolean restrictedBackupMode;
804 @UnsupportedAppUsage
805 boolean persistent;
806 Configuration config;
807 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
808 CompatibilityInfo compatInfo;
809 String buildSerial;
810
811 /** Initial values for {@link Profiler}. */
812 ProfilerInfo initProfilerInfo;
813
814 AutofillOptions autofillOptions;
815
816 /**
817 * Content capture options for the application - when null, it means ContentCapture is not
818 * enabled for the package.
819 */
820 @Nullable
821 ContentCaptureOptions contentCaptureOptions;
822
823 long[] disabledCompatChanges;
824
825 @Override
826 public String toString() {
827 return "AppBindData{appInfo=" + appInfo + "}";
828 }
829 }
830
831 static final class Profiler {
832 String profileFile;
833 ParcelFileDescriptor profileFd;
834 int samplingInterval;
835 boolean autoStopProfiler;
836 boolean streamingOutput;
837 boolean profiling;
838 boolean handlingProfiling;
839 public void setProfiler(ProfilerInfo profilerInfo) {
840 ParcelFileDescriptor fd = profilerInfo.profileFd;
841 if (profiling) {
842 if (fd != null) {
843 try {
844 fd.close();
845 } catch (IOException e) {
846 // Ignore
847 }
848 }
849 return;
850 }
851 if (profileFd != null) {
852 try {
853 profileFd.close();
854 } catch (IOException e) {
855 // Ignore
856 }
857 }
858 profileFile = profilerInfo.profileFile;
859 profileFd = fd;
860 samplingInterval = profilerInfo.samplingInterval;
861 autoStopProfiler = profilerInfo.autoStopProfiler;
862 streamingOutput = profilerInfo.streamingOutput;
863 }
864 public void startProfiling() {
865 if (profileFd == null || profiling) {
866 return;
867 }
868 try {
869 int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
870 VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
871 bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval,
872 streamingOutput);
873 profiling = true;
874 } catch (RuntimeException e) {
875 Slog.w(TAG, "Profiling failed on path " + profileFile, e);
876 try {
877 profileFd.close();
878 profileFd = null;
879 } catch (IOException e2) {
880 Slog.w(TAG, "Failure closing profile fd", e2);
881 }
882 }
883 }
884 public void stopProfiling() {
885 if (profiling) {
886 profiling = false;
887 Debug.stopMethodTracing();
888 if (profileFd != null) {
889 try {
890 profileFd.close();
891 } catch (IOException e) {
892 }
893 }
894 profileFd = null;
895 profileFile = null;
896 }
897 }
898 }
899
900 static final class DumpComponentInfo {
901 ParcelFileDescriptor fd;
902 IBinder token;
903 String prefix;
904 String[] args;
905 }
906
907 static final class ContextCleanupInfo {
908 ContextImpl context;
909 String what;
910 String who;
911 }
912
913 static final class DumpHeapData {
914 // Whether to dump the native or managed heap.
915 public boolean managed;
916 public boolean mallocInfo;
917 public boolean runGc;
918 String path;
919 ParcelFileDescriptor fd;
920 RemoteCallback finishCallback;
921 }
922
923 static final class UpdateCompatibilityData {
924 String pkg;
925 CompatibilityInfo info;
926 }
927
928 static final class RequestAssistContextExtras {
929 IBinder activityToken;
930 IBinder requestToken;
931 int requestType;
932 int sessionId;
933 int flags;
934 }
935
936 private class ApplicationThread extends IApplicationThread.Stub {
937 private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
938
939 public final void scheduleReceiver(Intent intent, ActivityInfo info,
940 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
941 boolean sync, int sendingUser, int processState) {
942 updateProcessState(processState, false);
943 ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
944 sync, false, mAppThread.asBinder(), sendingUser);
945 r.info = info;
946 r.compatInfo = compatInfo;
947 sendMessage(H.RECEIVER, r);
948 }
949
950 public final void scheduleCreateBackupAgent(ApplicationInfo app,
951 CompatibilityInfo compatInfo, int backupMode, int userId) {
952 CreateBackupAgentData d = new CreateBackupAgentData();
953 d.appInfo = app;
954 d.compatInfo = compatInfo;
955 d.backupMode = backupMode;
956 d.userId = userId;
957
958 sendMessage(H.CREATE_BACKUP_AGENT, d);
959 }
960
961 public final void scheduleDestroyBackupAgent(ApplicationInfo app,
962 CompatibilityInfo compatInfo, int userId) {
963 CreateBackupAgentData d = new CreateBackupAgentData();
964 d.appInfo = app;
965 d.compatInfo = compatInfo;
966 d.userId = userId;
967
968 sendMessage(H.DESTROY_BACKUP_AGENT, d);
969 }
970
971 public final void scheduleCreateService(IBinder token,
972 ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
973 updateProcessState(processState, false);
974 CreateServiceData s = new CreateServiceData();
975 s.token = token;
976 s.info = info;
977 s.compatInfo = compatInfo;
978
979 sendMessage(H.CREATE_SERVICE, s);
980 }
981
982 public final void scheduleBindService(IBinder token, Intent intent,
983 boolean rebind, int processState) {
984 updateProcessState(processState, false);
985 BindServiceData s = new BindServiceData();
986 s.token = token;
987 s.intent = intent;
988 s.rebind = rebind;
989
990 if (DEBUG_SERVICE)
991 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
992 + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
993 sendMessage(H.BIND_SERVICE, s);
994 }
995
996 public final void scheduleUnbindService(IBinder token, Intent intent) {
997 BindServiceData s = new BindServiceData();
998 s.token = token;
999 s.intent = intent;
1000
1001 sendMessage(H.UNBIND_SERVICE, s);
1002 }
1003
1004 public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
1005 List<ServiceStartArgs> list = args.getList();
1006
1007 for (int i = 0; i < list.size(); i++) {
1008 ServiceStartArgs ssa = list.get(i);
1009 ServiceArgsData s = new ServiceArgsData();
1010 s.token = token;
1011 s.taskRemoved = ssa.taskRemoved;
1012 s.startId = ssa.startId;
1013 s.flags = ssa.flags;
1014 s.args = ssa.args;
1015
1016 sendMessage(H.SERVICE_ARGS, s);
1017 }
1018 }
1019
1020 public final void scheduleStopService(IBinder token) {
1021 sendMessage(H.STOP_SERVICE, token);
1022 }
1023
1024 @Override
1025 public final void bindApplication(String processName, ApplicationInfo appInfo,
1026 ProviderInfoList providerList, ComponentName instrumentationName,
1027 ProfilerInfo profilerInfo, Bundle instrumentationArgs,
1028 IInstrumentationWatcher instrumentationWatcher,
1029 IUiAutomationConnection instrumentationUiConnection, int debugMode,
1030 boolean enableBinderTracking, boolean trackAllocation,
1031 boolean isRestrictedBackupMode, boolean persistent, Configuration config,
1032 CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
1033 String buildSerial, AutofillOptions autofillOptions,
1034 ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
1035 if (services != null) {
1036 if (false) {
1037 // Test code to make sure the app could see the passed-in services.
1038 for (Object oname : services.keySet()) {
1039 if (services.get(oname) == null) {
1040 continue; // AM just passed in a null service.
1041 }
1042 String name = (String) oname;
1043
1044 // See b/79378449 about the following exemption.
1045 switch (name) {
1046 case "package":
1047 case Context.WINDOW_SERVICE:
1048 continue;
1049 }
1050
1051 if (ServiceManager.getService(name) == null) {
1052 Log.wtf(TAG, "Service " + name + " should be accessible by this app");
1053 }
1054 }
1055 }
1056
1057 // Setup the service cache in the ServiceManager
1058 ServiceManager.initServiceCache(services);
1059 }
1060
1061 setCoreSettings(coreSettings);
1062
1063 AppBindData data = new AppBindData();
1064 data.processName = processName;
1065 data.appInfo = appInfo;
1066 data.providers = providerList.getList();
1067 data.instrumentationName = instrumentationName;
1068 data.instrumentationArgs = instrumentationArgs;
1069 data.instrumentationWatcher = instrumentationWatcher;
1070 data.instrumentationUiAutomationConnection = instrumentationUiConnection;
1071 data.debugMode = debugMode;
1072 data.enableBinderTracking = enableBinderTracking;
1073 data.trackAllocation = trackAllocation;
1074 data.restrictedBackupMode = isRestrictedBackupMode;
1075 data.persistent = persistent;
1076 data.config = config;
1077 data.compatInfo = compatInfo;
1078 data.initProfilerInfo = profilerInfo;
1079 data.buildSerial = buildSerial;
1080 data.autofillOptions = autofillOptions;
1081 data.contentCaptureOptions = contentCaptureOptions;
1082 data.disabledCompatChanges = disabledCompatChanges;
1083 sendMessage(H.BIND_APPLICATION, data);
1084 }
1085
1086 public final void runIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
1087 SomeArgs args = SomeArgs.obtain();
1088 args.arg1 = entryPoint;
1089 args.arg2 = entryPointArgs;
1090 sendMessage(H.RUN_ISOLATED_ENTRY_POINT, args);
1091 }
1092
1093 public final void scheduleExit() {
1094 sendMessage(H.EXIT_APPLICATION, null);
1095 }
1096
1097 public final void scheduleSuicide() {
1098 sendMessage(H.SUICIDE, null);
1099 }
1100
1101 public void scheduleApplicationInfoChanged(ApplicationInfo ai) {
1102 mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai);
1103 sendMessage(H.APPLICATION_INFO_CHANGED, ai);
1104 }
1105
1106 public void updateTimeZone() {
1107 TimeZone.setDefault(null);
1108 }
1109
1110 public void clearDnsCache() {
1111 // a non-standard API to get this to libcore
1112 InetAddress.clearDnsCache();
1113 // Allow libcore to perform the necessary actions as it sees fit upon a network
1114 // configuration change.
1115 NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged();
1116 }
1117
1118 public void updateHttpProxy() {
1119 ActivityThread.updateHttpProxy(
1120 getApplication() != null ? getApplication() : getSystemContext());
1121 }
1122
1123 public void processInBackground() {
1124 mH.removeMessages(H.GC_WHEN_IDLE);
1125 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
1126 }
1127
1128 public void dumpService(ParcelFileDescriptor pfd, IBinder servicetoken, String[] args) {
1129 DumpComponentInfo data = new DumpComponentInfo();
1130 try {
1131 data.fd = pfd.dup();
1132 data.token = servicetoken;
1133 data.args = args;
1134 sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/);
1135 } catch (IOException e) {
1136 Slog.w(TAG, "dumpService failed", e);
1137 } finally {
1138 IoUtils.closeQuietly(pfd);
1139 }
1140 }
1141
1142 // This function exists to make sure all receiver dispatching is
1143 // correctly ordered, since these are one-way calls and the binder driver
1144 // applies transaction ordering per object for such calls.
1145 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
1146 int resultCode, String dataStr, Bundle extras, boolean ordered,
1147 boolean sticky, int sendingUser, int processState) throws RemoteException {
1148 updateProcessState(processState, false);
1149 receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
1150 sticky, sendingUser);
1151 }
1152
1153 @Override
1154 public void scheduleLowMemory() {
1155 sendMessage(H.LOW_MEMORY, null);
1156 }
1157
1158 @Override
1159 public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
1160 sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType);
1161 }
1162
1163 @Override
1164 public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
1165 ParcelFileDescriptor fd, RemoteCallback finishCallback) {
1166 DumpHeapData dhd = new DumpHeapData();
1167 dhd.managed = managed;
1168 dhd.mallocInfo = mallocInfo;
1169 dhd.runGc = runGc;
1170 dhd.path = path;
1171 try {
1172 // Since we're going to dump the heap asynchronously, dup the file descriptor before
1173 // it's closed on returning from the IPC call.
1174 dhd.fd = fd.dup();
1175 } catch (IOException e) {
1176 Slog.e(TAG, "Failed to duplicate heap dump file descriptor", e);
1177 return;
1178 } finally {
1179 IoUtils.closeQuietly(fd);
1180 }
1181 dhd.finishCallback = finishCallback;
1182 sendMessage(H.DUMP_HEAP, dhd, 0, 0, true /*async*/);
1183 }
1184
1185 public void attachAgent(String agent) {
1186 sendMessage(H.ATTACH_AGENT, agent);
1187 }
1188
1189 public void attachStartupAgents(String dataDir) {
1190 sendMessage(H.ATTACH_STARTUP_AGENTS, dataDir);
1191 }
1192
1193 public void setSchedulingGroup(int group) {
1194 // Note: do this immediately, since going into the foreground
1195 // should happen regardless of what pending work we have to do
1196 // and the activity manager will wait for us to report back that
1197 // we are done before sending us to the background.
1198 try {
1199 Process.setProcessGroup(Process.myPid(), group);
1200 } catch (Exception e) {
1201 Slog.w(TAG, "Failed setting process group to " + group, e);
1202 }
1203 }
1204
1205 public void dispatchPackageBroadcast(int cmd, String[] packages) {
1206 sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
1207 }
1208
1209 public void scheduleCrash(String msg) {
1210 sendMessage(H.SCHEDULE_CRASH, msg);
1211 }
1212
1213 public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
1214 String prefix, String[] args) {
1215 DumpComponentInfo data = new DumpComponentInfo();
1216 try {
1217 data.fd = pfd.dup();
1218 data.token = activitytoken;
1219 data.prefix = prefix;
1220 data.args = args;
1221 sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/);
1222 } catch (IOException e) {
1223 Slog.w(TAG, "dumpActivity failed", e);
1224 } finally {
1225 IoUtils.closeQuietly(pfd);
1226 }
1227 }
1228
1229 public void dumpProvider(ParcelFileDescriptor pfd, IBinder providertoken,
1230 String[] args) {
1231 DumpComponentInfo data = new DumpComponentInfo();
1232 try {
1233 data.fd = pfd.dup();
1234 data.token = providertoken;
1235 data.args = args;
1236 sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/);
1237 } catch (IOException e) {
1238 Slog.w(TAG, "dumpProvider failed", e);
1239 } finally {
1240 IoUtils.closeQuietly(pfd);
1241 }
1242 }
1243
1244 @Override
1245 public void dumpMemInfo(ParcelFileDescriptor pfd, Debug.MemoryInfo mem, boolean checkin,
1246 boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
1247 boolean dumpUnreachable, String[] args) {
1248 FileOutputStream fout = new FileOutputStream(pfd.getFileDescriptor());
1249 PrintWriter pw = new FastPrintWriter(fout);
1250 try {
1251 dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
1252 } finally {
1253 pw.flush();
1254 IoUtils.closeQuietly(pfd);
1255 }
1256 }
1257
1258 private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
1259 boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
1260 long nativeMax = Debug.getNativeHeapSize() / 1024;
1261 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1262 long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1263
1264 Runtime runtime = Runtime.getRuntime();
1265 runtime.gc(); // Do GC since countInstancesOfClass counts unreachable objects.
1266 long dalvikMax = runtime.totalMemory() / 1024;
1267 long dalvikFree = runtime.freeMemory() / 1024;
1268 long dalvikAllocated = dalvikMax - dalvikFree;
1269
1270 Class[] classesToCount = new Class[] {
1271 ContextImpl.class,
1272 Activity.class,
1273 WebView.class,
1274 OpenSSLSocketImpl.class
1275 };
1276 long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
1277 long appContextInstanceCount = instanceCounts[0];
1278 long activityInstanceCount = instanceCounts[1];
1279 long webviewInstanceCount = instanceCounts[2];
1280 long openSslSocketCount = instanceCounts[3];
1281
1282 long viewInstanceCount = ViewDebug.getViewInstanceCount();
1283 long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
1284 int globalAssetCount = AssetManager.getGlobalAssetCount();
1285 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1286 int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1287 int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1288 int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1289 long parcelSize = Parcel.getGlobalAllocSize();
1290 long parcelCount = Parcel.getGlobalAllocCount();
1291 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
1292
1293 dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
1294 Process.myPid(),
1295 (mBoundApplication != null) ? mBoundApplication.processName : "unknown",
1296 nativeMax, nativeAllocated, nativeFree,
1297 dalvikMax, dalvikAllocated, dalvikFree);
1298
1299 if (checkin) {
1300 // NOTE: if you change anything significant below, also consider changing
1301 // ACTIVITY_THREAD_CHECKIN_VERSION.
1302
1303 // Object counts
1304 pw.print(viewInstanceCount); pw.print(',');
1305 pw.print(viewRootInstanceCount); pw.print(',');
1306 pw.print(appContextInstanceCount); pw.print(',');
1307 pw.print(activityInstanceCount); pw.print(',');
1308
1309 pw.print(globalAssetCount); pw.print(',');
1310 pw.print(globalAssetManagerCount); pw.print(',');
1311 pw.print(binderLocalObjectCount); pw.print(',');
1312 pw.print(binderProxyObjectCount); pw.print(',');
1313
1314 pw.print(binderDeathObjectCount); pw.print(',');
1315 pw.print(openSslSocketCount); pw.print(',');
1316
1317 // SQL
1318 pw.print(stats.memoryUsed / 1024); pw.print(',');
1319 pw.print(stats.memoryUsed / 1024); pw.print(',');
1320 pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
1321 pw.print(stats.largestMemAlloc / 1024);
1322 for (int i = 0; i < stats.dbStats.size(); i++) {
1323 DbStats dbStats = stats.dbStats.get(i);
1324 pw.print(','); pw.print(dbStats.dbName);
1325 pw.print(','); pw.print(dbStats.pageSize);
1326 pw.print(','); pw.print(dbStats.dbSize);
1327 pw.print(','); pw.print(dbStats.lookaside);
1328 pw.print(','); pw.print(dbStats.cache);
1329 pw.print(','); pw.print(dbStats.cache);
1330 }
1331 pw.println();
1332
1333 return;
1334 }
1335
1336 pw.println(" ");
1337 pw.println(" Objects");
1338 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
1339 viewRootInstanceCount);
1340
1341 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1342 "Activities:", activityInstanceCount);
1343
1344 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1345 "AssetManagers:", globalAssetManagerCount);
1346
1347 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1348 "Proxy Binders:", binderProxyObjectCount);
1349 printRow(pw, TWO_COUNT_COLUMNS, "Parcel memory:", parcelSize/1024,
1350 "Parcel count:", parcelCount);
1351 printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount,
1352 "OpenSSL Sockets:", openSslSocketCount);
1353 printRow(pw, ONE_COUNT_COLUMN, "WebViews:", webviewInstanceCount);
1354
1355 // SQLite mem info
1356 pw.println(" ");
1357 pw.println(" SQL");
1358 printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
1359 printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
1360 stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
1361 pw.println(" ");
1362 int N = stats.dbStats.size();
1363 if (N > 0) {
1364 pw.println(" DATABASES");
1365 printRow(pw, DB_INFO_FORMAT, "pgsz", "dbsz", "Lookaside(b)", "cache",
1366 "Dbname");
1367 for (int i = 0; i < N; i++) {
1368 DbStats dbStats = stats.dbStats.get(i);
1369 printRow(pw, DB_INFO_FORMAT,
1370 (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
1371 (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
1372 (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
1373 dbStats.cache, dbStats.dbName);
1374 }
1375 }
1376
1377 // Asset details.
1378 String assetAlloc = AssetManager.getAssetAllocations();
1379 if (assetAlloc != null) {
1380 pw.println(" ");
1381 pw.println(" Asset Allocations");
1382 pw.print(assetAlloc);
1383 }
1384
1385 // Unreachable native memory
1386 if (dumpUnreachable) {
1387 boolean showContents = ((mBoundApplication != null)
1388 && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
1389 || android.os.Build.IS_DEBUGGABLE;
1390 pw.println(" ");
1391 pw.println(" Unreachable memory");
1392 pw.print(Debug.getUnreachableMemory(100, showContents));
1393 }
1394 }
1395
1396 @Override
1397 public void dumpMemInfoProto(ParcelFileDescriptor pfd, Debug.MemoryInfo mem,
1398 boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
1399 boolean dumpUnreachable, String[] args) {
1400 ProtoOutputStream proto = new ProtoOutputStream(pfd.getFileDescriptor());
1401 try {
1402 dumpMemInfo(proto, mem, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
1403 } finally {
1404 proto.flush();
1405 IoUtils.closeQuietly(pfd);
1406 }
1407 }
1408
1409 private void dumpMemInfo(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
1410 boolean dumpFullInfo, boolean dumpDalvik,
1411 boolean dumpSummaryOnly, boolean dumpUnreachable) {
1412 long nativeMax = Debug.getNativeHeapSize() / 1024;
1413 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1414 long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1415
1416 Runtime runtime = Runtime.getRuntime();
1417 runtime.gc(); // Do GC since countInstancesOfClass counts unreachable objects.
1418 long dalvikMax = runtime.totalMemory() / 1024;
1419 long dalvikFree = runtime.freeMemory() / 1024;
1420 long dalvikAllocated = dalvikMax - dalvikFree;
1421
1422 Class[] classesToCount = new Class[] {
1423 ContextImpl.class,
1424 Activity.class,
1425 WebView.class,
1426 OpenSSLSocketImpl.class
1427 };
1428 long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
1429 long appContextInstanceCount = instanceCounts[0];
1430 long activityInstanceCount = instanceCounts[1];
1431 long webviewInstanceCount = instanceCounts[2];
1432 long openSslSocketCount = instanceCounts[3];
1433
1434 long viewInstanceCount = ViewDebug.getViewInstanceCount();
1435 long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
1436 int globalAssetCount = AssetManager.getGlobalAssetCount();
1437 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1438 int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1439 int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1440 int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1441 long parcelSize = Parcel.getGlobalAllocSize();
1442 long parcelCount = Parcel.getGlobalAllocCount();
1443 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
1444
1445 final long mToken = proto.start(MemInfoDumpProto.AppData.PROCESS_MEMORY);
1446 proto.write(MemInfoDumpProto.ProcessMemory.PID, Process.myPid());
1447 proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME,
1448 (mBoundApplication != null) ? mBoundApplication.processName : "unknown");
1449 dumpMemInfoTable(proto, memInfo, dumpDalvik, dumpSummaryOnly,
1450 nativeMax, nativeAllocated, nativeFree,
1451 dalvikMax, dalvikAllocated, dalvikFree);
1452 proto.end(mToken);
1453
1454 final long oToken = proto.start(MemInfoDumpProto.AppData.OBJECTS);
1455 proto.write(MemInfoDumpProto.AppData.ObjectStats.VIEW_INSTANCE_COUNT,
1456 viewInstanceCount);
1457 proto.write(MemInfoDumpProto.AppData.ObjectStats.VIEW_ROOT_INSTANCE_COUNT,
1458 viewRootInstanceCount);
1459 proto.write(MemInfoDumpProto.AppData.ObjectStats.APP_CONTEXT_INSTANCE_COUNT,
1460 appContextInstanceCount);
1461 proto.write(MemInfoDumpProto.AppData.ObjectStats.ACTIVITY_INSTANCE_COUNT,
1462 activityInstanceCount);
1463 proto.write(MemInfoDumpProto.AppData.ObjectStats.GLOBAL_ASSET_COUNT,
1464 globalAssetCount);
1465 proto.write(MemInfoDumpProto.AppData.ObjectStats.GLOBAL_ASSET_MANAGER_COUNT,
1466 globalAssetManagerCount);
1467 proto.write(MemInfoDumpProto.AppData.ObjectStats.LOCAL_BINDER_OBJECT_COUNT,
1468 binderLocalObjectCount);
1469 proto.write(MemInfoDumpProto.AppData.ObjectStats.PROXY_BINDER_OBJECT_COUNT,
1470 binderProxyObjectCount);
1471 proto.write(MemInfoDumpProto.AppData.ObjectStats.PARCEL_MEMORY_KB,
1472 parcelSize / 1024);
1473 proto.write(MemInfoDumpProto.AppData.ObjectStats.PARCEL_COUNT, parcelCount);
1474 proto.write(MemInfoDumpProto.AppData.ObjectStats.BINDER_OBJECT_DEATH_COUNT,
1475 binderDeathObjectCount);
1476 proto.write(MemInfoDumpProto.AppData.ObjectStats.OPEN_SSL_SOCKET_COUNT,
1477 openSslSocketCount);
1478 proto.write(MemInfoDumpProto.AppData.ObjectStats.WEBVIEW_INSTANCE_COUNT,
1479 webviewInstanceCount);
1480 proto.end(oToken);
1481
1482 // SQLite mem info
1483 final long sToken = proto.start(MemInfoDumpProto.AppData.SQL);
1484 proto.write(MemInfoDumpProto.AppData.SqlStats.MEMORY_USED_KB,
1485 stats.memoryUsed / 1024);
1486 proto.write(MemInfoDumpProto.AppData.SqlStats.PAGECACHE_OVERFLOW_KB,
1487 stats.pageCacheOverflow / 1024);
1488 proto.write(MemInfoDumpProto.AppData.SqlStats.MALLOC_SIZE_KB,
1489 stats.largestMemAlloc / 1024);
1490 int n = stats.dbStats.size();
1491 for (int i = 0; i < n; i++) {
1492 DbStats dbStats = stats.dbStats.get(i);
1493
1494 final long dToken = proto.start(MemInfoDumpProto.AppData.SqlStats.DATABASES);
1495 proto.write(MemInfoDumpProto.AppData.SqlStats.Database.NAME, dbStats.dbName);
1496 proto.write(MemInfoDumpProto.AppData.SqlStats.Database.PAGE_SIZE, dbStats.pageSize);
1497 proto.write(MemInfoDumpProto.AppData.SqlStats.Database.DB_SIZE, dbStats.dbSize);
1498 proto.write(MemInfoDumpProto.AppData.SqlStats.Database.LOOKASIDE_B,
1499 dbStats.lookaside);
1500 proto.write(MemInfoDumpProto.AppData.SqlStats.Database.CACHE, dbStats.cache);
1501 proto.end(dToken);
1502 }
1503 proto.end(sToken);
1504
1505 // Asset details.
1506 String assetAlloc = AssetManager.getAssetAllocations();
1507 if (assetAlloc != null) {
1508 proto.write(MemInfoDumpProto.AppData.ASSET_ALLOCATIONS, assetAlloc);
1509 }
1510
1511 // Unreachable native memory
1512 if (dumpUnreachable) {
1513 int flags = mBoundApplication == null ? 0 : mBoundApplication.appInfo.flags;
1514 boolean showContents = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0
1515 || android.os.Build.IS_DEBUGGABLE;
1516 proto.write(MemInfoDumpProto.AppData.UNREACHABLE_MEMORY,
1517 Debug.getUnreachableMemory(100, showContents));
1518 }
1519 }
1520
1521 @Override
1522 public void dumpGfxInfo(ParcelFileDescriptor pfd, String[] args) {
1523 nDumpGraphicsInfo(pfd.getFileDescriptor());
1524 WindowManagerGlobal.getInstance().dumpGfxInfo(pfd.getFileDescriptor(), args);
1525 IoUtils.closeQuietly(pfd);
1526 }
1527
1528 private File getDatabasesDir(Context context) {
1529 // There's no simple way to get the databases/ path, so do it this way.
1530 return context.getDatabasePath("a").getParentFile();
1531 }
1532
1533 private void dumpDatabaseInfo(ParcelFileDescriptor pfd, String[] args, boolean isSystem) {
1534 PrintWriter pw = new FastPrintWriter(
1535 new FileOutputStream(pfd.getFileDescriptor()));
1536 PrintWriterPrinter printer = new PrintWriterPrinter(pw);
1537 SQLiteDebug.dump(printer, args, isSystem);
1538 pw.flush();
1539 }
1540
1541 @Override
1542 public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) {
1543 if (mSystemThread) {
1544 // Ensure this invocation is asynchronous to prevent writer waiting if buffer cannot
1545 // be consumed. But it must duplicate the file descriptor first, since caller might
1546 // be closing it.
1547 final ParcelFileDescriptor dup;
1548 try {
1549 dup = pfd.dup();
1550 } catch (IOException e) {
1551 Log.w(TAG, "Could not dup FD " + pfd.getFileDescriptor().getInt$());
1552 return;
1553 } finally {
1554 IoUtils.closeQuietly(pfd);
1555 }
1556
1557 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1558 @Override
1559 public void run() {
1560 try {
1561 dumpDatabaseInfo(dup, args, true);
1562 } finally {
1563 IoUtils.closeQuietly(dup);
1564 }
1565 }
1566 });
1567 } else {
1568 dumpDatabaseInfo(pfd, args, false);
1569 IoUtils.closeQuietly(pfd);
1570 }
1571 }
1572
1573 @Override
1574 public void unstableProviderDied(IBinder provider) {
1575 sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
1576 }
1577
1578 @Override
1579 public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
1580 int requestType, int sessionId, int flags) {
1581 RequestAssistContextExtras cmd = new RequestAssistContextExtras();
1582 cmd.activityToken = activityToken;
1583 cmd.requestToken = requestToken;
1584 cmd.requestType = requestType;
1585 cmd.sessionId = sessionId;
1586 cmd.flags = flags;
1587 sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
1588 }
1589
1590 public void setCoreSettings(Bundle coreSettings) {
1591 sendMessage(H.SET_CORE_SETTINGS, coreSettings);
1592 }
1593
1594 public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
1595 UpdateCompatibilityData ucd = new UpdateCompatibilityData();
1596 ucd.pkg = pkg;
1597 ucd.info = info;
1598 sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
1599 }
1600
1601 public void scheduleTrimMemory(int level) {
1602 final Runnable r = PooledLambda.obtainRunnable(ActivityThread::handleTrimMemory,
1603 ActivityThread.this, level).recycleOnUse();
1604 // Schedule trimming memory after drawing the frame to minimize jank-risk.
1605 Choreographer choreographer = Choreographer.getMainThreadInstance();
1606 if (choreographer != null) {
1607 choreographer.postCallback(Choreographer.CALLBACK_COMMIT, r, null);
1608 } else {
1609 mH.post(r);
1610 }
1611 }
1612
1613 public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
1614 sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
1615 }
1616
1617 public void scheduleOnNewActivityOptions(IBinder token, Bundle options) {
1618 sendMessage(H.ON_NEW_ACTIVITY_OPTIONS,
1619 new Pair<IBinder, ActivityOptions>(token, ActivityOptions.fromBundle(options)));
1620 }
1621
1622 public void setProcessState(int state) {
1623 updateProcessState(state, true);
1624 }
1625
1626 /**
1627 * Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
1628 * the main thread that it needs to wait for the network rules to get updated before
1629 * launching an activity.
1630 */
1631 @Override
1632 public void setNetworkBlockSeq(long procStateSeq) {
1633 synchronized (mNetworkPolicyLock) {
1634 mNetworkBlockSeq = procStateSeq;
1635 }
1636 }
1637
1638 @Override
1639 public void scheduleInstallProvider(ProviderInfo provider) {
1640 sendMessage(H.INSTALL_PROVIDER, provider);
1641 }
1642
1643 @Override
1644 public final void updateTimePrefs(int timeFormatPreference) {
1645 final Boolean timeFormatPreferenceBool;
1646 // For convenience we are using the Intent extra values.
1647 if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR) {
1648 timeFormatPreferenceBool = Boolean.FALSE;
1649 } else if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR) {
1650 timeFormatPreferenceBool = Boolean.TRUE;
1651 } else {
1652 // timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT
1653 // (or unknown).
1654 timeFormatPreferenceBool = null;
1655 }
1656 DateFormat.set24HourTimePref(timeFormatPreferenceBool);
1657 }
1658
1659 @Override
1660 public void scheduleEnterAnimationComplete(IBinder token) {
1661 sendMessage(H.ENTER_ANIMATION_COMPLETE, token);
1662 }
1663
1664 @Override
1665 public void notifyCleartextNetwork(byte[] firstPacket) {
1666 if (StrictMode.vmCleartextNetworkEnabled()) {
1667 StrictMode.onCleartextNetworkDetected(firstPacket);
1668 }
1669 }
1670
1671 @Override
1672 public void startBinderTracking() {
1673 sendMessage(H.START_BINDER_TRACKING, null);
1674 }
1675
1676 @Override
1677 public void stopBinderTrackingAndDump(ParcelFileDescriptor pfd) {
1678 try {
1679 sendMessage(H.STOP_BINDER_TRACKING_AND_DUMP, pfd.dup());
1680 } catch (IOException e) {
1681 } finally {
1682 IoUtils.closeQuietly(pfd);
1683 }
1684 }
1685
1686 @Override
1687 public void scheduleLocalVoiceInteractionStarted(IBinder token,
1688 IVoiceInteractor voiceInteractor) throws RemoteException {
1689 SomeArgs args = SomeArgs.obtain();
1690 args.arg1 = token;
1691 args.arg2 = voiceInteractor;
1692 sendMessage(H.LOCAL_VOICE_INTERACTION_STARTED, args);
1693 }
1694
1695 @Override
1696 public void handleTrustStorageUpdate() {
1697 NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
1698 }
1699
1700 @Override
1701 public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
1702 ActivityThread.this.scheduleTransaction(transaction);
1703 }
1704
1705 @Override
1706 public void requestDirectActions(@NonNull IBinder activityToken,
1707 @NonNull IVoiceInteractor interactor, @Nullable RemoteCallback cancellationCallback,
1708 @NonNull RemoteCallback callback) {
1709 final CancellationSignal cancellationSignal = new CancellationSignal();
1710 if (cancellationCallback != null) {
1711 final ICancellationSignal transport = createSafeCancellationTransport(
1712 cancellationSignal);
1713 final Bundle cancellationResult = new Bundle();
1714 cancellationResult.putBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL,
1715 transport.asBinder());
1716 cancellationCallback.sendResult(cancellationResult);
1717 }
1718 mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handleRequestDirectActions,
1719 ActivityThread.this, activityToken, interactor, cancellationSignal, callback));
1720 }
1721
1722 @Override
1723 public void performDirectAction(@NonNull IBinder activityToken, @NonNull String actionId,
1724 @Nullable Bundle arguments, @Nullable RemoteCallback cancellationCallback,
1725 @NonNull RemoteCallback resultCallback) {
1726 final CancellationSignal cancellationSignal = new CancellationSignal();
1727 if (cancellationCallback != null) {
1728 final ICancellationSignal transport = createSafeCancellationTransport(
1729 cancellationSignal);
1730 final Bundle cancellationResult = new Bundle();
1731 cancellationResult.putBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL,
1732 transport.asBinder());
1733 cancellationCallback.sendResult(cancellationResult);
1734 }
1735 mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handlePerformDirectAction,
1736 ActivityThread.this, activityToken, actionId, arguments,
1737 cancellationSignal, resultCallback));
1738 }
1739 }
1740
1741 private @NonNull SafeCancellationTransport createSafeCancellationTransport(
1742 @NonNull CancellationSignal cancellationSignal) {
1743 synchronized (ActivityThread.this) {
1744 if (mRemoteCancellations == null) {
1745 mRemoteCancellations = new ArrayMap<>();
1746 }
1747 final SafeCancellationTransport transport = new SafeCancellationTransport(
1748 this, cancellationSignal);
1749 mRemoteCancellations.put(transport, cancellationSignal);
1750 return transport;
1751 }
1752 }
1753
1754 private @NonNull CancellationSignal removeSafeCancellationTransport(
1755 @NonNull SafeCancellationTransport transport) {
1756 synchronized (ActivityThread.this) {
1757 final CancellationSignal cancellation = mRemoteCancellations.remove(transport);
1758 if (mRemoteCancellations.isEmpty()) {
1759 mRemoteCancellations = null;
1760 }
1761 return cancellation;
1762 }
1763 }
1764
1765 private static final class SafeCancellationTransport extends ICancellationSignal.Stub {
1766 private final @NonNull WeakReference<ActivityThread> mWeakActivityThread;
1767
1768 SafeCancellationTransport(@NonNull ActivityThread activityThread,
1769 @NonNull CancellationSignal cancellation) {
1770 mWeakActivityThread = new WeakReference<>(activityThread);
1771 }
1772
1773 @Override
1774 public void cancel() {
1775 final ActivityThread activityThread = mWeakActivityThread.get();
1776 if (activityThread != null) {
1777 final CancellationSignal cancellation = activityThread
1778 .removeSafeCancellationTransport(this);
1779 if (cancellation != null) {
1780 cancellation.cancel();
1781 }
1782 }
1783 }
1784 }
1785
1786 class H extends Handler {
1787 public static final int BIND_APPLICATION = 110;
1788 @UnsupportedAppUsage
1789 public static final int EXIT_APPLICATION = 111;
1790 @UnsupportedAppUsage
1791 public static final int RECEIVER = 113;
1792 @UnsupportedAppUsage
1793 public static final int CREATE_SERVICE = 114;
1794 @UnsupportedAppUsage
1795 public static final int SERVICE_ARGS = 115;
1796 @UnsupportedAppUsage
1797 public static final int STOP_SERVICE = 116;
1798
1799 public static final int CONFIGURATION_CHANGED = 118;
1800 public static final int CLEAN_UP_CONTEXT = 119;
1801 @UnsupportedAppUsage
1802 public static final int GC_WHEN_IDLE = 120;
1803 @UnsupportedAppUsage
1804 public static final int BIND_SERVICE = 121;
1805 @UnsupportedAppUsage
1806 public static final int UNBIND_SERVICE = 122;
1807 public static final int DUMP_SERVICE = 123;
1808 public static final int LOW_MEMORY = 124;
1809 public static final int PROFILER_CONTROL = 127;
1810 public static final int CREATE_BACKUP_AGENT = 128;
1811 public static final int DESTROY_BACKUP_AGENT = 129;
1812 public static final int SUICIDE = 130;
1813 @UnsupportedAppUsage
1814 public static final int REMOVE_PROVIDER = 131;
1815 public static final int DISPATCH_PACKAGE_BROADCAST = 133;
1816 @UnsupportedAppUsage
1817 public static final int SCHEDULE_CRASH = 134;
1818 public static final int DUMP_HEAP = 135;
1819 public static final int DUMP_ACTIVITY = 136;
1820 public static final int SLEEPING = 137;
1821 public static final int SET_CORE_SETTINGS = 138;
1822 public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
1823 @UnsupportedAppUsage
1824 public static final int DUMP_PROVIDER = 141;
1825 public static final int UNSTABLE_PROVIDER_DIED = 142;
1826 public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
1827 public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
1828 @UnsupportedAppUsage
1829 public static final int INSTALL_PROVIDER = 145;
1830 public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
1831 @UnsupportedAppUsage
1832 public static final int ENTER_ANIMATION_COMPLETE = 149;
1833 public static final int START_BINDER_TRACKING = 150;
1834 public static final int STOP_BINDER_TRACKING_AND_DUMP = 151;
1835 public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
1836 public static final int ATTACH_AGENT = 155;
1837 public static final int APPLICATION_INFO_CHANGED = 156;
1838 public static final int RUN_ISOLATED_ENTRY_POINT = 158;
1839 public static final int EXECUTE_TRANSACTION = 159;
1840 public static final int RELAUNCH_ACTIVITY = 160;
1841 public static final int PURGE_RESOURCES = 161;
1842 public static final int ATTACH_STARTUP_AGENTS = 162;
1843
1844 String codeToString(int code) {
1845 if (DEBUG_MESSAGES) {
1846 switch (code) {
1847 case BIND_APPLICATION: return "BIND_APPLICATION";
1848 case EXIT_APPLICATION: return "EXIT_APPLICATION";
1849 case RECEIVER: return "RECEIVER";
1850 case CREATE_SERVICE: return "CREATE_SERVICE";
1851 case SERVICE_ARGS: return "SERVICE_ARGS";
1852 case STOP_SERVICE: return "STOP_SERVICE";
1853 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1854 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1855 case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1856 case BIND_SERVICE: return "BIND_SERVICE";
1857 case UNBIND_SERVICE: return "UNBIND_SERVICE";
1858 case DUMP_SERVICE: return "DUMP_SERVICE";
1859 case LOW_MEMORY: return "LOW_MEMORY";
1860 case PROFILER_CONTROL: return "PROFILER_CONTROL";
1861 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1862 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
1863 case SUICIDE: return "SUICIDE";
1864 case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
1865 case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
1866 case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
1867 case DUMP_HEAP: return "DUMP_HEAP";
1868 case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
1869 case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
1870 case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
1871 case DUMP_PROVIDER: return "DUMP_PROVIDER";
1872 case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
1873 case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
1874 case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
1875 case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
1876 case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
1877 case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
1878 case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
1879 case ATTACH_AGENT: return "ATTACH_AGENT";
1880 case APPLICATION_INFO_CHANGED: return "APPLICATION_INFO_CHANGED";
1881 case RUN_ISOLATED_ENTRY_POINT: return "RUN_ISOLATED_ENTRY_POINT";
1882 case EXECUTE_TRANSACTION: return "EXECUTE_TRANSACTION";
1883 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
1884 case PURGE_RESOURCES: return "PURGE_RESOURCES";
1885 case ATTACH_STARTUP_AGENTS: return "ATTACH_STARTUP_AGENTS";
1886 }
1887 }
1888 return Integer.toString(code);
1889 }
1890 public void handleMessage(Message msg) {
1891 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
1892 switch (msg.what) {
1893 case BIND_APPLICATION:
1894 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
1895 AppBindData data = (AppBindData)msg.obj;
1896 handleBindApplication(data);
1897 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1898 break;
1899 case EXIT_APPLICATION:
1900 if (mInitialApplication != null) {
1901 mInitialApplication.onTerminate();
1902 }
1903 Looper.myLooper().quit();
1904 break;
1905 case RECEIVER:
1906 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
1907 handleReceiver((ReceiverData)msg.obj);
1908 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1909 break;
1910 case CREATE_SERVICE:
1911 if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
1912 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1913 ("serviceCreate: " + String.valueOf(msg.obj)));
1914 }
1915 handleCreateService((CreateServiceData)msg.obj);
1916 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1917 break;
1918 case BIND_SERVICE:
1919 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
1920 handleBindService((BindServiceData)msg.obj);
1921 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1922 break;
1923 case UNBIND_SERVICE:
1924 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
1925 handleUnbindService((BindServiceData)msg.obj);
1926 schedulePurgeIdler();
1927 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1928 break;
1929 case SERVICE_ARGS:
1930 if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
1931 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1932 ("serviceStart: " + String.valueOf(msg.obj)));
1933 }
1934 handleServiceArgs((ServiceArgsData)msg.obj);
1935 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1936 break;
1937 case STOP_SERVICE:
1938 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
1939 handleStopService((IBinder)msg.obj);
1940 schedulePurgeIdler();
1941 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1942 break;
1943 case CONFIGURATION_CHANGED:
1944 handleConfigurationChanged((Configuration) msg.obj);
1945 break;
1946 case CLEAN_UP_CONTEXT:
1947 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1948 cci.context.performFinalCleanup(cci.who, cci.what);
1949 break;
1950 case GC_WHEN_IDLE:
1951 scheduleGcIdler();
1952 break;
1953 case DUMP_SERVICE:
1954 handleDumpService((DumpComponentInfo)msg.obj);
1955 break;
1956 case LOW_MEMORY:
1957 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
1958 handleLowMemory();
1959 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1960 break;
1961 case PROFILER_CONTROL:
1962 handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
1963 break;
1964 case CREATE_BACKUP_AGENT:
1965 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
1966 handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1967 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1968 break;
1969 case DESTROY_BACKUP_AGENT:
1970 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
1971 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1972 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1973 break;
1974 case SUICIDE:
1975 Process.killProcess(Process.myPid());
1976 break;
1977 case REMOVE_PROVIDER:
1978 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
1979 completeRemoveProvider((ProviderRefCount)msg.obj);
1980 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1981 break;
1982 case DISPATCH_PACKAGE_BROADCAST:
1983 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
1984 handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
1985 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1986 break;
1987 case SCHEDULE_CRASH:
1988 throw new RemoteServiceException((String)msg.obj);
1989 case DUMP_HEAP:
1990 handleDumpHeap((DumpHeapData) msg.obj);
1991 break;
1992 case DUMP_ACTIVITY:
1993 handleDumpActivity((DumpComponentInfo)msg.obj);
1994 break;
1995 case DUMP_PROVIDER:
1996 handleDumpProvider((DumpComponentInfo)msg.obj);
1997 break;
1998 case SET_CORE_SETTINGS:
1999 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
2000 handleSetCoreSettings((Bundle) msg.obj);
2001 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
2002 break;
2003 case UPDATE_PACKAGE_COMPATIBILITY_INFO:
2004 handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
2005 break;
2006 case UNSTABLE_PROVIDER_DIED:
2007 handleUnstableProviderDied((IBinder)msg.obj, false);
2008 break;
2009 case REQUEST_ASSIST_CONTEXT_EXTRAS:
2010 handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
2011 break;
2012 case TRANSLUCENT_CONVERSION_COMPLETE:
2013 handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
2014 break;
2015 case INSTALL_PROVIDER:
2016 handleInstallProvider((ProviderInfo) msg.obj);
2017 break;
2018 case ON_NEW_ACTIVITY_OPTIONS:
2019 Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
2020 onNewActivityOptions(pair.first, pair.second);
2021 break;
2022 case ENTER_ANIMATION_COMPLETE:
2023 handleEnterAnimationComplete((IBinder) msg.obj);
2024 break;
2025 case START_BINDER_TRACKING:
2026 handleStartBinderTracking();
2027 break;
2028 case STOP_BINDER_TRACKING_AND_DUMP:
2029 handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
2030 break;
2031 case LOCAL_VOICE_INTERACTION_STARTED:
2032 handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
2033 (IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
2034 break;
2035 case ATTACH_AGENT: {
2036 Application app = getApplication();
2037 handleAttachAgent((String) msg.obj, app != null ? app.mLoadedApk : null);
2038 break;
2039 }
2040 case APPLICATION_INFO_CHANGED:
2041 handleApplicationInfoChanged((ApplicationInfo) msg.obj);
2042 break;
2043 case RUN_ISOLATED_ENTRY_POINT:
2044 handleRunIsolatedEntryPoint((String) ((SomeArgs) msg.obj).arg1,
2045 (String[]) ((SomeArgs) msg.obj).arg2);
2046 break;
2047 case EXECUTE_TRANSACTION:
2048 final ClientTransaction transaction = (ClientTransaction) msg.obj;
2049 mTransactionExecutor.execute(transaction);
2050 if (isSystem()) {
2051 // Client transactions inside system process are recycled on the client side
2052 // instead of ClientLifecycleManager to avoid being cleared before this
2053 // message is handled.
2054 transaction.recycle();
2055 }
2056 // TODO(lifecycler): Recycle locally scheduled transactions.
2057 break;
2058 case RELAUNCH_ACTIVITY:
2059 handleRelaunchActivityLocally((IBinder) msg.obj);
2060 break;
2061 case PURGE_RESOURCES:
2062 schedulePurgeIdler();
2063 break;
2064 case ATTACH_STARTUP_AGENTS:
2065 handleAttachStartupAgents((String) msg.obj);
2066 break;
2067 }
2068 Object obj = msg.obj;
2069 if (obj instanceof SomeArgs) {
2070 ((SomeArgs) obj).recycle();
2071 }
2072 if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
2073 }
2074 }
2075
2076 private class Idler implements MessageQueue.IdleHandler {
2077 @Override
2078 public final boolean queueIdle() {
2079 ActivityClientRecord a = mNewActivities;
2080 boolean stopProfiling = false;
2081 if (mBoundApplication != null && mProfiler.profileFd != null
2082 && mProfiler.autoStopProfiler) {
2083 stopProfiling = true;
2084 }
2085 if (a != null) {
2086 mNewActivities = null;
2087 IActivityTaskManager am = ActivityTaskManager.getService();
2088 ActivityClientRecord prev;
2089 do {
2090 if (localLOGV) Slog.v(
2091 TAG, "Reporting idle of " + a +
2092 " finished=" +
2093 (a.activity != null && a.activity.mFinished));
2094 if (a.activity != null && !a.activity.mFinished) {
2095 try {
2096 am.activityIdle(a.token, a.createdConfig, stopProfiling);
2097 a.createdConfig = null;
2098 } catch (RemoteException ex) {
2099 throw ex.rethrowFromSystemServer();
2100 }
2101 }
2102 prev = a;
2103 a = a.nextIdle;
2104 prev.nextIdle = null;
2105 } while (a != null);
2106 }
2107 if (stopProfiling) {
2108 mProfiler.stopProfiling();
2109 }
2110 applyPendingProcessState();
2111 return false;
2112 }
2113 }
2114
2115 final class GcIdler implements MessageQueue.IdleHandler {
2116 @Override
2117 public final boolean queueIdle() {
2118 doGcIfNeeded();
2119 purgePendingResources();
2120 return false;
2121 }
2122 }
2123
2124 final class PurgeIdler implements MessageQueue.IdleHandler {
2125 @Override
2126 public boolean queueIdle() {
2127 purgePendingResources();
2128 return false;
2129 }
2130 }
2131
2132 @UnsupportedAppUsage
2133 public static ActivityThread currentActivityThread() {
2134 return sCurrentActivityThread;
2135 }
2136
2137 public static boolean isSystem() {
2138 return (sCurrentActivityThread != null) ? sCurrentActivityThread.mSystemThread : false;
2139 }
2140
2141 public static String currentOpPackageName() {
2142 ActivityThread am = currentActivityThread();
2143 return (am != null && am.getApplication() != null)
2144 ? am.getApplication().getOpPackageName() : null;
2145 }
2146
2147 @UnsupportedAppUsage
2148 public static String currentPackageName() {
2149 ActivityThread am = currentActivityThread();
2150 return (am != null && am.mBoundApplication != null)
2151 ? am.mBoundApplication.appInfo.packageName : null;
2152 }
2153
2154 @UnsupportedAppUsage
2155 public static String currentProcessName() {
2156 ActivityThread am = currentActivityThread();
2157 return (am != null && am.mBoundApplication != null)
2158 ? am.mBoundApplication.processName : null;
2159 }
2160
2161 @UnsupportedAppUsage
2162 public static Application currentApplication() {
2163 ActivityThread am = currentActivityThread();
2164 return am != null ? am.mInitialApplication : null;
2165 }
2166
2167 @UnsupportedAppUsage
2168 public static IPackageManager getPackageManager() {
2169 if (sPackageManager != null) {
2170 return sPackageManager;
2171 }
2172 final IBinder b = ServiceManager.getService("package");
2173 sPackageManager = IPackageManager.Stub.asInterface(b);
2174 return sPackageManager;
2175 }
2176
2177 /** Returns the permission manager */
2178 public static IPermissionManager getPermissionManager() {
2179 if (sPermissionManager != null) {
2180 return sPermissionManager;
2181 }
2182 final IBinder b = ServiceManager.getService("permissionmgr");
2183 sPermissionManager = IPermissionManager.Stub.asInterface(b);
2184 return sPermissionManager;
2185 }
2186
2187 private Configuration mMainThreadConfig = new Configuration();
2188
2189 Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
2190 CompatibilityInfo compat) {
2191 if (config == null) {
2192 return null;
2193 }
2194 if (!compat.supportsScreen()) {
2195 mMainThreadConfig.setTo(config);
2196 config = mMainThreadConfig;
2197 compat.applyToConfiguration(displayDensity, config);
2198 }
2199 return config;
2200 }
2201
2202 /**
2203 * Creates the top level resources for the given package. Will return an existing
2204 * Resources if one has already been created.
2205 */
2206 Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
2207 String[] libDirs, int displayId, LoadedApk pkgInfo) {
2208 return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
2209 displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), null);
2210 }
2211
2212 @UnsupportedAppUsage
2213 final Handler getHandler() {
2214 return mH;
2215 }
2216
2217 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2218 public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
2219 int flags) {
2220 return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
2221 }
2222
2223 public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
2224 int flags, int userId) {
2225 final boolean differentUser = (UserHandle.myUserId() != userId);
2226 ApplicationInfo ai = PackageManager.getApplicationInfoAsUserCached(
2227 packageName,
2228 PackageManager.GET_SHARED_LIBRARY_FILES
2229 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
2230 (userId < 0) ? UserHandle.myUserId() : userId);
2231 synchronized (mResourcesManager) {
2232 WeakReference<LoadedApk> ref;
2233 if (differentUser) {
2234 // Caching not supported across users
2235 ref = null;
2236 } else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) {
2237 ref = mPackages.get(packageName);
2238 } else {
2239 ref = mResourcePackages.get(packageName);
2240 }
2241
2242 LoadedApk packageInfo = ref != null ? ref.get() : null;
2243 if (ai != null && packageInfo != null) {
2244 if (!isLoadedApkResourceDirsUpToDate(packageInfo, ai)) {
2245 List<String> oldPaths = new ArrayList<>();
2246 LoadedApk.makePaths(this, ai, oldPaths);
2247 packageInfo.updateApplicationInfo(ai, oldPaths);
2248 }
2249
2250 if (packageInfo.isSecurityViolation()
2251 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
2252 throw new SecurityException(
2253 "Requesting code from " + packageName
2254 + " to be run in process "
2255 + mBoundApplication.processName
2256 + "/" + mBoundApplication.appInfo.uid);
2257 }
2258 return packageInfo;
2259 }
2260 }
2261
2262 if (ai != null) {
2263 return getPackageInfo(ai, compatInfo, flags);
2264 }
2265
2266 return null;
2267 }
2268
2269 @UnsupportedAppUsage
2270 public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
2271 int flags) {
2272 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
2273 boolean securityViolation = includeCode && ai.uid != 0
2274 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
2275 ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
2276 : true);
2277 boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
2278 if ((flags&(Context.CONTEXT_INCLUDE_CODE
2279 |Context.CONTEXT_IGNORE_SECURITY))
2280 == Context.CONTEXT_INCLUDE_CODE) {
2281 if (securityViolation) {
2282 String msg = "Requesting code from " + ai.packageName
2283 + " (with uid " + ai.uid + ")";
2284 if (mBoundApplication != null) {
2285 msg = msg + " to be run in process "
2286 + mBoundApplication.processName + " (with uid "
2287 + mBoundApplication.appInfo.uid + ")";
2288 }
2289 throw new SecurityException(msg);
2290 }
2291 }
2292 return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
2293 registerPackage);
2294 }
2295
2296 @Override
2297 @UnsupportedAppUsage
2298 public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
2299 CompatibilityInfo compatInfo) {
2300 return getPackageInfo(ai, compatInfo, null, false, true, false);
2301 }
2302
2303 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
2304 public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
2305 synchronized (mResourcesManager) {
2306 WeakReference<LoadedApk> ref;
2307 if (includeCode) {
2308 ref = mPackages.get(packageName);
2309 } else {
2310 ref = mResourcePackages.get(packageName);
2311 }
2312 return ref != null ? ref.get() : null;
2313 }
2314 }
2315
2316 private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
2317 ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
2318 boolean registerPackage) {
2319 final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
2320 synchronized (mResourcesManager) {
2321 WeakReference<LoadedApk> ref;
2322 if (differentUser) {
2323 // Caching not supported across users
2324 ref = null;
2325 } else if (includeCode) {
2326 ref = mPackages.get(aInfo.packageName);
2327 } else {
2328 ref = mResourcePackages.get(aInfo.packageName);
2329 }
2330
2331 LoadedApk packageInfo = ref != null ? ref.get() : null;
2332
2333 if (packageInfo != null) {
2334 if (!isLoadedApkResourceDirsUpToDate(packageInfo, aInfo)) {
2335 List<String> oldPaths = new ArrayList<>();
2336 LoadedApk.makePaths(this, aInfo, oldPaths);
2337 packageInfo.updateApplicationInfo(aInfo, oldPaths);
2338 }
2339
2340 return packageInfo;
2341 }
2342
2343 if (localLOGV) {
2344 Slog.v(TAG, (includeCode ? "Loading code package "
2345 : "Loading resource-only package ") + aInfo.packageName
2346 + " (in " + (mBoundApplication != null
2347 ? mBoundApplication.processName : null)
2348 + ")");
2349 }
2350
2351 packageInfo =
2352 new LoadedApk(this, aInfo, compatInfo, baseLoader,
2353 securityViolation, includeCode
2354 && (aInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
2355
2356 if (mSystemThread && "android".equals(aInfo.packageName)) {
2357 packageInfo.installSystemApplicationInfo(aInfo,
2358 getSystemContext().mPackageInfo.getClassLoader());
2359 }
2360
2361 if (differentUser) {
2362 // Caching not supported across users
2363 } else if (includeCode) {
2364 mPackages.put(aInfo.packageName,
2365 new WeakReference<LoadedApk>(packageInfo));
2366 } else {
2367 mResourcePackages.put(aInfo.packageName,
2368 new WeakReference<LoadedApk>(packageInfo));
2369 }
2370
2371 return packageInfo;
2372 }
2373 }
2374
2375 private static boolean isLoadedApkResourceDirsUpToDate(LoadedApk loadedApk,
2376 ApplicationInfo appInfo) {
2377 Resources packageResources = loadedApk.mResources;
2378 String[] overlayDirs = ArrayUtils.defeatNullable(loadedApk.getOverlayDirs());
2379 String[] resourceDirs = ArrayUtils.defeatNullable(appInfo.resourceDirs);
2380
2381 return (packageResources == null || packageResources.getAssets().isUpToDate())
2382 && overlayDirs.length == resourceDirs.length
2383 && ArrayUtils.containsAll(overlayDirs, resourceDirs);
2384 }
2385
2386 @UnsupportedAppUsage
2387 ActivityThread() {
2388 mResourcesManager = ResourcesManager.getInstance();
2389 }
2390
2391 @UnsupportedAppUsage
2392 public ApplicationThread getApplicationThread()
2393 {
2394 return mAppThread;
2395 }
2396
2397 @UnsupportedAppUsage
2398 public Instrumentation getInstrumentation()
2399 {
2400 return mInstrumentation;
2401 }
2402
2403 public boolean isProfiling() {
2404 return mProfiler != null && mProfiler.profileFile != null
2405 && mProfiler.profileFd == null;
2406 }
2407
2408 public String getProfileFilePath() {
2409 return mProfiler.profileFile;
2410 }
2411
2412 @UnsupportedAppUsage
2413 public Looper getLooper() {
2414 return mLooper;
2415 }
2416
2417 public Executor getExecutor() {
2418 return mExecutor;
2419 }
2420
2421 @UnsupportedAppUsage
2422 public Application getApplication() {
2423 return mInitialApplication;
2424 }
2425
2426 @UnsupportedAppUsage
2427 public String getProcessName() {
2428 return mBoundApplication.processName;
2429 }
2430
2431 @UnsupportedAppUsage
2432 public ContextImpl getSystemContext() {
2433 synchronized (this) {
2434 if (mSystemContext == null) {
2435 mSystemContext = ContextImpl.createSystemContext(this);
2436 }
2437 return mSystemContext;
2438 }
2439 }
2440
2441 public ContextImpl getSystemUiContext() {
2442 synchronized (this) {
2443 if (mSystemUiContext == null) {
2444 mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
2445 }
2446 return mSystemUiContext;
2447 }
2448 }
2449
2450 /**
2451 * Create the context instance base on system resources & display information which used for UI.
2452 * @param displayId The ID of the display where the UI is shown.
2453 * @see ContextImpl#createSystemUiContext(ContextImpl, int)
2454 */
2455 public ContextImpl createSystemUiContext(int displayId) {
2456 return ContextImpl.createSystemUiContext(getSystemUiContext(), displayId);
2457 }
2458
2459 public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
2460 synchronized (this) {
2461 getSystemContext().installSystemApplicationInfo(info, classLoader);
2462 getSystemUiContext().installSystemApplicationInfo(info, classLoader);
2463
2464 // give ourselves a default profiler
2465 mProfiler = new Profiler();
2466 }
2467 }
2468
2469 @UnsupportedAppUsage
2470 void scheduleGcIdler() {
2471 if (!mGcIdlerScheduled) {
2472 mGcIdlerScheduled = true;
2473 Looper.myQueue().addIdleHandler(mGcIdler);
2474 }
2475 mH.removeMessages(H.GC_WHEN_IDLE);
2476 }
2477
2478 void unscheduleGcIdler() {
2479 if (mGcIdlerScheduled) {
2480 mGcIdlerScheduled = false;
2481 Looper.myQueue().removeIdleHandler(mGcIdler);
2482 }
2483 mH.removeMessages(H.GC_WHEN_IDLE);
2484 }
2485
2486 void schedulePurgeIdler() {
2487 if (!mPurgeIdlerScheduled) {
2488 mPurgeIdlerScheduled = true;
2489 Looper.myQueue().addIdleHandler(mPurgeIdler);
2490 }
2491 mH.removeMessages(H.PURGE_RESOURCES);
2492 }
2493
2494 void unschedulePurgeIdler() {
2495 if (mPurgeIdlerScheduled) {
2496 mPurgeIdlerScheduled = false;
2497 Looper.myQueue().removeIdleHandler(mPurgeIdler);
2498 }
2499 mH.removeMessages(H.PURGE_RESOURCES);
2500 }
2501
2502 void doGcIfNeeded() {
2503 doGcIfNeeded("bg");
2504 }
2505
2506 void doGcIfNeeded(String reason) {
2507 mGcIdlerScheduled = false;
2508 final long now = SystemClock.uptimeMillis();
2509 //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
2510 // + "m now=" + now);
2511 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
2512 //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
2513 BinderInternal.forceGc(reason);
2514 }
2515 }
2516
2517 private static final String HEAP_FULL_COLUMN =
2518 "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
2519 private static final String HEAP_COLUMN =
2520 "%13s %8s %8s %8s %8s %8s %8s %8s %8s";
2521 private static final String ONE_COUNT_COLUMN = "%21s %8d";
2522 private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
2523 private static final String THREE_COUNT_COLUMNS = "%21s %8d %21s %8s %21s %8d";
2524 private static final String TWO_COUNT_COLUMN_HEADER = "%21s %8s %21s %8s";
2525 private static final String ONE_ALT_COUNT_COLUMN = "%21s %8s %21s %8d";
2526
2527 // Formatting for checkin service - update version if row format changes
2528 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
2529
2530 static void printRow(PrintWriter pw, String format, Object...objs) {
2531 pw.println(String.format(format, objs));
2532 }
2533
2534 public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
2535 boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
2536 int pid, String processName,
2537 long nativeMax, long nativeAllocated, long nativeFree,
2538 long dalvikMax, long dalvikAllocated, long dalvikFree) {
2539
2540 // For checkin, we print one long comma-separated list of values
2541 if (checkin) {
2542 // NOTE: if you change anything significant below, also consider changing
2543 // ACTIVITY_THREAD_CHECKIN_VERSION.
2544
2545 // Header
2546 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
2547 pw.print(pid); pw.print(',');
2548 pw.print(processName); pw.print(',');
2549
2550 // Heap info - max
2551 pw.print(nativeMax); pw.print(',');
2552 pw.print(dalvikMax); pw.print(',');
2553 pw.print("N/A,");
2554 pw.print(nativeMax + dalvikMax); pw.print(',');
2555
2556 // Heap info - allocated
2557 pw.print(nativeAllocated); pw.print(',');
2558 pw.print(dalvikAllocated); pw.print(',');
2559 pw.print("N/A,");
2560 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
2561
2562 // Heap info - free
2563 pw.print(nativeFree); pw.print(',');
2564 pw.print(dalvikFree); pw.print(',');
2565 pw.print("N/A,");
2566 pw.print(nativeFree + dalvikFree); pw.print(',');
2567
2568 // Heap info - proportional set size
2569 pw.print(memInfo.nativePss); pw.print(',');
2570 pw.print(memInfo.dalvikPss); pw.print(',');
2571 pw.print(memInfo.otherPss); pw.print(',');
2572 pw.print(memInfo.getTotalPss()); pw.print(',');
2573
2574 // Heap info - swappable set size
2575 pw.print(memInfo.nativeSwappablePss); pw.print(',');
2576 pw.print(memInfo.dalvikSwappablePss); pw.print(',');
2577 pw.print(memInfo.otherSwappablePss); pw.print(',');
2578 pw.print(memInfo.getTotalSwappablePss()); pw.print(',');
2579
2580 // Heap info - shared dirty
2581 pw.print(memInfo.nativeSharedDirty); pw.print(',');
2582 pw.print(memInfo.dalvikSharedDirty); pw.print(',');
2583 pw.print(memInfo.otherSharedDirty); pw.print(',');
2584 pw.print(memInfo.getTotalSharedDirty()); pw.print(',');
2585
2586 // Heap info - shared clean
2587 pw.print(memInfo.nativeSharedClean); pw.print(',');
2588 pw.print(memInfo.dalvikSharedClean); pw.print(',');
2589 pw.print(memInfo.otherSharedClean); pw.print(',');
2590 pw.print(memInfo.getTotalSharedClean()); pw.print(',');
2591
2592 // Heap info - private Dirty
2593 pw.print(memInfo.nativePrivateDirty); pw.print(',');
2594 pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
2595 pw.print(memInfo.otherPrivateDirty); pw.print(',');
2596 pw.print(memInfo.getTotalPrivateDirty()); pw.print(',');
2597
2598 // Heap info - private Clean
2599 pw.print(memInfo.nativePrivateClean); pw.print(',');
2600 pw.print(memInfo.dalvikPrivateClean); pw.print(',');
2601 pw.print(memInfo.otherPrivateClean); pw.print(',');
2602 pw.print(memInfo.getTotalPrivateClean()); pw.print(',');
2603
2604 // Heap info - swapped out
2605 pw.print(memInfo.nativeSwappedOut); pw.print(',');
2606 pw.print(memInfo.dalvikSwappedOut); pw.print(',');
2607 pw.print(memInfo.otherSwappedOut); pw.print(',');
2608 pw.print(memInfo.getTotalSwappedOut()); pw.print(',');
2609
2610 // Heap info - swapped out pss
2611 if (memInfo.hasSwappedOutPss) {
2612 pw.print(memInfo.nativeSwappedOutPss); pw.print(',');
2613 pw.print(memInfo.dalvikSwappedOutPss); pw.print(',');
2614 pw.print(memInfo.otherSwappedOutPss); pw.print(',');
2615 pw.print(memInfo.getTotalSwappedOutPss()); pw.print(',');
2616 } else {
2617 pw.print("N/A,");
2618 pw.print("N/A,");
2619 pw.print("N/A,");
2620 pw.print("N/A,");
2621 }
2622
2623 // Heap info - other areas
2624 for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
2625 pw.print(Debug.MemoryInfo.getOtherLabel(i)); pw.print(',');
2626 pw.print(memInfo.getOtherPss(i)); pw.print(',');
2627 pw.print(memInfo.getOtherSwappablePss(i)); pw.print(',');
2628 pw.print(memInfo.getOtherSharedDirty(i)); pw.print(',');
2629 pw.print(memInfo.getOtherSharedClean(i)); pw.print(',');
2630 pw.print(memInfo.getOtherPrivateDirty(i)); pw.print(',');
2631 pw.print(memInfo.getOtherPrivateClean(i)); pw.print(',');
2632 pw.print(memInfo.getOtherSwappedOut(i)); pw.print(',');
2633 if (memInfo.hasSwappedOutPss) {
2634 pw.print(memInfo.getOtherSwappedOutPss(i)); pw.print(',');
2635 } else {
2636 pw.print("N/A,");
2637 }
2638 }
2639 return;
2640 }
2641
2642 if (!dumpSummaryOnly) {
2643 if (dumpFullInfo) {
2644 printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
2645 "Shared", "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
2646 "Rss", "Heap", "Heap", "Heap");
2647 printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
2648 "Clean", "Clean", "Dirty", "Total",
2649 "Size", "Alloc", "Free");
2650 printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
2651 "------", "------", "------", "------", "------", "------", "------");
2652 printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
2653 memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
2654 memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
2655 memInfo.nativePrivateClean, memInfo.hasSwappedOutPss ?
2656 memInfo.nativeSwappedOutPss : memInfo.nativeSwappedOut,
2657 memInfo.nativeRss, nativeMax, nativeAllocated, nativeFree);
2658 printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
2659 memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
2660 memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
2661 memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?
2662 memInfo.dalvikSwappedOutPss : memInfo.dalvikSwappedOut,
2663 memInfo.dalvikRss, dalvikMax, dalvikAllocated, dalvikFree);
2664 } else {
2665 printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
2666 "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
2667 "Rss", "Heap", "Heap", "Heap");
2668 printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
2669 "Clean", "Dirty", "Total", "Size", "Alloc", "Free");
2670 printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
2671 "------", "------", "------", "------", "------", "------");
2672 printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
2673 memInfo.nativePrivateDirty,
2674 memInfo.nativePrivateClean,
2675 memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
2676 memInfo.nativeSwappedOut, memInfo.nativeRss,
2677 nativeMax, nativeAllocated, nativeFree);
2678 printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
2679 memInfo.dalvikPrivateDirty,
2680 memInfo.dalvikPrivateClean,
2681 memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
2682 memInfo.dalvikSwappedOut, memInfo.dalvikRss,
2683 dalvikMax, dalvikAllocated, dalvikFree);
2684 }
2685
2686 int otherPss = memInfo.otherPss;
2687 int otherSwappablePss = memInfo.otherSwappablePss;
2688 int otherSharedDirty = memInfo.otherSharedDirty;
2689 int otherPrivateDirty = memInfo.otherPrivateDirty;
2690 int otherSharedClean = memInfo.otherSharedClean;
2691 int otherPrivateClean = memInfo.otherPrivateClean;
2692 int otherSwappedOut = memInfo.otherSwappedOut;
2693 int otherSwappedOutPss = memInfo.otherSwappedOutPss;
2694 int otherRss = memInfo.otherRss;
2695
2696 for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
2697 final int myPss = memInfo.getOtherPss(i);
2698 final int mySwappablePss = memInfo.getOtherSwappablePss(i);
2699 final int mySharedDirty = memInfo.getOtherSharedDirty(i);
2700 final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
2701 final int mySharedClean = memInfo.getOtherSharedClean(i);
2702 final int myPrivateClean = memInfo.getOtherPrivateClean(i);
2703 final int mySwappedOut = memInfo.getOtherSwappedOut(i);
2704 final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
2705 final int myRss = memInfo.getOtherRss(i);
2706 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
2707 || mySharedClean != 0 || myPrivateClean != 0 || myRss != 0
2708 || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
2709 if (dumpFullInfo) {
2710 printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2711 myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
2712 mySharedClean, myPrivateClean,
2713 memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2714 myRss, "", "", "");
2715 } else {
2716 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2717 myPss, myPrivateDirty,
2718 myPrivateClean,
2719 memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2720 myRss, "", "", "");
2721 }
2722 otherPss -= myPss;
2723 otherSwappablePss -= mySwappablePss;
2724 otherSharedDirty -= mySharedDirty;
2725 otherPrivateDirty -= myPrivateDirty;
2726 otherSharedClean -= mySharedClean;
2727 otherPrivateClean -= myPrivateClean;
2728 otherSwappedOut -= mySwappedOut;
2729 otherSwappedOutPss -= mySwappedOutPss;
2730 otherRss -= myRss;
2731 }
2732 }
2733
2734 if (dumpFullInfo) {
2735 printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
2736 otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
2737 memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
2738 otherRss, "", "", "");
2739 printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
2740 memInfo.getTotalSwappablePss(),
2741 memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
2742 memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
2743 memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
2744 memInfo.getTotalSwappedOut(), memInfo.getTotalRss(),
2745 nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
2746 nativeFree+dalvikFree);
2747 } else {
2748 printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
2749 otherPrivateDirty, otherPrivateClean,
2750 memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
2751 otherRss, "", "", "");
2752 printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
2753 memInfo.getTotalPrivateDirty(),
2754 memInfo.getTotalPrivateClean(),
2755 memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
2756 memInfo.getTotalSwappedOut(), memInfo.getTotalPss(),
2757 nativeMax+dalvikMax,
2758 nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
2759 }
2760
2761 if (dumpDalvik) {
2762 pw.println(" ");
2763 pw.println(" Dalvik Details");
2764
2765 for (int i=Debug.MemoryInfo.NUM_OTHER_STATS;
2766 i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) {
2767 final int myPss = memInfo.getOtherPss(i);
2768 final int mySwappablePss = memInfo.getOtherSwappablePss(i);
2769 final int mySharedDirty = memInfo.getOtherSharedDirty(i);
2770 final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
2771 final int mySharedClean = memInfo.getOtherSharedClean(i);
2772 final int myPrivateClean = memInfo.getOtherPrivateClean(i);
2773 final int mySwappedOut = memInfo.getOtherSwappedOut(i);
2774 final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
2775 final int myRss = memInfo.getOtherRss(i);
2776 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
2777 || mySharedClean != 0 || myPrivateClean != 0
2778 || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
2779 if (dumpFullInfo) {
2780 printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2781 myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
2782 mySharedClean, myPrivateClean,
2783 memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2784 myRss, "", "", "");
2785 } else {
2786 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2787 myPss, myPrivateDirty,
2788 myPrivateClean,
2789 memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2790 myRss, "", "", "");
2791 }
2792 }
2793 }
2794 }
2795 }
2796
2797 pw.println(" ");
2798 pw.println(" App Summary");
2799 printRow(pw, TWO_COUNT_COLUMN_HEADER, "", "Pss(KB)", "", "Rss(KB)");
2800 printRow(pw, TWO_COUNT_COLUMN_HEADER, "", "------", "", "------");
2801 printRow(pw, TWO_COUNT_COLUMNS,
2802 "Java Heap:", memInfo.getSummaryJavaHeap(), "", memInfo.getSummaryJavaHeapRss());
2803 printRow(pw, TWO_COUNT_COLUMNS,
2804 "Native Heap:", memInfo.getSummaryNativeHeap(), "",
2805 memInfo.getSummaryNativeHeapRss());
2806 printRow(pw, TWO_COUNT_COLUMNS,
2807 "Code:", memInfo.getSummaryCode(), "", memInfo.getSummaryCodeRss());
2808 printRow(pw, TWO_COUNT_COLUMNS,
2809 "Stack:", memInfo.getSummaryStack(), "", memInfo.getSummaryStackRss());
2810 printRow(pw, TWO_COUNT_COLUMNS,
2811 "Graphics:", memInfo.getSummaryGraphics(), "", memInfo.getSummaryGraphicsRss());
2812 printRow(pw, ONE_COUNT_COLUMN,
2813 "Private Other:", memInfo.getSummaryPrivateOther());
2814 printRow(pw, ONE_COUNT_COLUMN,
2815 "System:", memInfo.getSummarySystem());
2816 printRow(pw, ONE_ALT_COUNT_COLUMN,
2817 "Unknown:", "", "", memInfo.getSummaryUnknownRss());
2818 pw.println(" ");
2819 if (memInfo.hasSwappedOutPss) {
2820 printRow(pw, THREE_COUNT_COLUMNS,
2821 "TOTAL PSS:", memInfo.getSummaryTotalPss(),
2822 "TOTAL RSS:", memInfo.getTotalRss(),
2823 "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
2824 } else {
2825 printRow(pw, THREE_COUNT_COLUMNS,
2826 "TOTAL PSS:", memInfo.getSummaryTotalPss(),
2827 "TOTAL RSS:", memInfo.getTotalRss(),
2828 "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
2829 }
2830 }
2831
2832 /**
2833 * Dump heap info to proto.
2834 *
2835 * @param hasSwappedOutPss determines whether to use dirtySwap or dirtySwapPss
2836 */
2837 private static void dumpMemoryInfo(ProtoOutputStream proto, long fieldId, String name,
2838 int pss, int cleanPss, int sharedDirty, int privateDirty,
2839 int sharedClean, int privateClean,
2840 boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss, int rss) {
2841 final long token = proto.start(fieldId);
2842
2843 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.NAME, name);
2844 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.TOTAL_PSS_KB, pss);
2845 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.CLEAN_PSS_KB, cleanPss);
2846 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.SHARED_DIRTY_KB, sharedDirty);
2847 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.PRIVATE_DIRTY_KB, privateDirty);
2848 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.SHARED_CLEAN_KB, sharedClean);
2849 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.PRIVATE_CLEAN_KB, privateClean);
2850 if (hasSwappedOutPss) {
2851 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_PSS_KB, dirtySwapPss);
2852 } else {
2853 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_KB, dirtySwap);
2854 }
2855 proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.TOTAL_RSS_KB, rss);
2856
2857 proto.end(token);
2858 }
2859
2860 /**
2861 * Dump mem info data to proto.
2862 */
2863 public static void dumpMemInfoTable(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
2864 boolean dumpDalvik, boolean dumpSummaryOnly,
2865 long nativeMax, long nativeAllocated, long nativeFree,
2866 long dalvikMax, long dalvikAllocated, long dalvikFree) {
2867
2868 if (!dumpSummaryOnly) {
2869 final long nhToken = proto.start(MemInfoDumpProto.ProcessMemory.NATIVE_HEAP);
2870 dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "Native Heap",
2871 memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
2872 memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
2873 memInfo.nativePrivateClean, memInfo.hasSwappedOutPss,
2874 memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss,
2875 memInfo.nativeRss);
2876 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, nativeMax);
2877 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, nativeAllocated);
2878 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, nativeFree);
2879 proto.end(nhToken);
2880
2881 final long dvToken = proto.start(MemInfoDumpProto.ProcessMemory.DALVIK_HEAP);
2882 dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "Dalvik Heap",
2883 memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
2884 memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
2885 memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss,
2886 memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss,
2887 memInfo.dalvikRss);
2888 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, dalvikMax);
2889 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated);
2890 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, dalvikFree);
2891 proto.end(dvToken);
2892
2893 int otherPss = memInfo.otherPss;
2894 int otherSwappablePss = memInfo.otherSwappablePss;
2895 int otherSharedDirty = memInfo.otherSharedDirty;
2896 int otherPrivateDirty = memInfo.otherPrivateDirty;
2897 int otherSharedClean = memInfo.otherSharedClean;
2898 int otherPrivateClean = memInfo.otherPrivateClean;
2899 int otherSwappedOut = memInfo.otherSwappedOut;
2900 int otherSwappedOutPss = memInfo.otherSwappedOutPss;
2901 int otherRss = memInfo.otherRss;
2902
2903 for (int i = 0; i < Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
2904 final int myPss = memInfo.getOtherPss(i);
2905 final int mySwappablePss = memInfo.getOtherSwappablePss(i);
2906 final int mySharedDirty = memInfo.getOtherSharedDirty(i);
2907 final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
2908 final int mySharedClean = memInfo.getOtherSharedClean(i);
2909 final int myPrivateClean = memInfo.getOtherPrivateClean(i);
2910 final int mySwappedOut = memInfo.getOtherSwappedOut(i);
2911 final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
2912 final int myRss = memInfo.getOtherRss(i);
2913 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
2914 || mySharedClean != 0 || myPrivateClean != 0 || myRss != 0
2915 || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
2916 dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.OTHER_HEAPS,
2917 Debug.MemoryInfo.getOtherLabel(i),
2918 myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
2919 mySharedClean, myPrivateClean,
2920 memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss, myRss);
2921
2922 otherPss -= myPss;
2923 otherSwappablePss -= mySwappablePss;
2924 otherSharedDirty -= mySharedDirty;
2925 otherPrivateDirty -= myPrivateDirty;
2926 otherSharedClean -= mySharedClean;
2927 otherPrivateClean -= myPrivateClean;
2928 otherSwappedOut -= mySwappedOut;
2929 otherSwappedOutPss -= mySwappedOutPss;
2930 otherRss -= myRss;
2931 }
2932 }
2933
2934 dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.UNKNOWN_HEAP, "Unknown",
2935 otherPss, otherSwappablePss,
2936 otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
2937 memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss, otherRss);
2938 final long tToken = proto.start(MemInfoDumpProto.ProcessMemory.TOTAL_HEAP);
2939 dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "TOTAL",
2940 memInfo.getTotalPss(), memInfo.getTotalSwappablePss(),
2941 memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
2942 memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
2943 memInfo.hasSwappedOutPss, memInfo.getTotalSwappedOut(),
2944 memInfo.getTotalSwappedOutPss(), memInfo.getTotalRss());
2945 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB,
2946 nativeMax + dalvikMax);
2947 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB,
2948 nativeAllocated + dalvikAllocated);
2949 proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB,
2950 nativeFree + dalvikFree);
2951 proto.end(tToken);
2952
2953 if (dumpDalvik) {
2954 for (int i = Debug.MemoryInfo.NUM_OTHER_STATS;
2955 i < Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS;
2956 i++) {
2957 final int myPss = memInfo.getOtherPss(i);
2958 final int mySwappablePss = memInfo.getOtherSwappablePss(i);
2959 final int mySharedDirty = memInfo.getOtherSharedDirty(i);
2960 final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
2961 final int mySharedClean = memInfo.getOtherSharedClean(i);
2962 final int myPrivateClean = memInfo.getOtherPrivateClean(i);
2963 final int mySwappedOut = memInfo.getOtherSwappedOut(i);
2964 final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
2965 final int myRss = memInfo.getOtherRss(i);
2966 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
2967 || mySharedClean != 0 || myPrivateClean != 0
2968 || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
2969 dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.DALVIK_DETAILS,
2970 Debug.MemoryInfo.getOtherLabel(i),
2971 myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
2972 mySharedClean, myPrivateClean,
2973 memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss, myRss);
2974 }
2975 }
2976 }
2977 }
2978
2979 final long asToken = proto.start(MemInfoDumpProto.ProcessMemory.APP_SUMMARY);
2980 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.JAVA_HEAP_PSS_KB,
2981 memInfo.getSummaryJavaHeap());
2982 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.NATIVE_HEAP_PSS_KB,
2983 memInfo.getSummaryNativeHeap());
2984 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.CODE_PSS_KB,
2985 memInfo.getSummaryCode());
2986 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.STACK_PSS_KB,
2987 memInfo.getSummaryStack());
2988 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.GRAPHICS_PSS_KB,
2989 memInfo.getSummaryGraphics());
2990 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.PRIVATE_OTHER_PSS_KB,
2991 memInfo.getSummaryPrivateOther());
2992 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.SYSTEM_PSS_KB,
2993 memInfo.getSummarySystem());
2994 if (memInfo.hasSwappedOutPss) {
2995 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS,
2996 memInfo.getSummaryTotalSwapPss());
2997 } else {
2998 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS,
2999 memInfo.getSummaryTotalSwap());
3000 }
3001 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.JAVA_HEAP_RSS_KB,
3002 memInfo.getSummaryJavaHeapRss());
3003 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.NATIVE_HEAP_RSS_KB,
3004 memInfo.getSummaryNativeHeapRss());
3005 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.CODE_RSS_KB,
3006 memInfo.getSummaryCodeRss());
3007 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.STACK_RSS_KB,
3008 memInfo.getSummaryStackRss());
3009 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.GRAPHICS_RSS_KB,
3010 memInfo.getSummaryGraphicsRss());
3011 proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.UNKNOWN_RSS_KB,
3012 memInfo.getSummaryUnknownRss());
3013
3014 proto.end(asToken);
3015 }
3016
3017 @UnsupportedAppUsage
3018 public void registerOnActivityPausedListener(Activity activity,
3019 OnActivityPausedListener listener) {
3020 synchronized (mOnPauseListeners) {
3021 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
3022 if (list == null) {
3023 list = new ArrayList<OnActivityPausedListener>();
3024 mOnPauseListeners.put(activity, list);
3025 }
3026 list.add(listener);
3027 }
3028 }
3029
3030 @UnsupportedAppUsage
3031 public void unregisterOnActivityPausedListener(Activity activity,
3032 OnActivityPausedListener listener) {
3033 synchronized (mOnPauseListeners) {
3034 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
3035 if (list != null) {
3036 list.remove(listener);
3037 }
3038 }
3039 }
3040
3041 public final ActivityInfo resolveActivityInfo(Intent intent) {
3042 ActivityInfo aInfo = intent.resolveActivityInfo(
3043 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
3044 if (aInfo == null) {
3045 // Throw an exception.
3046 Instrumentation.checkStartActivityResult(
3047 ActivityManager.START_CLASS_NOT_FOUND, intent);
3048 }
3049 return aInfo;
3050 }
3051
3052 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3053 public final Activity startActivityNow(Activity parent, String id,
3054 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
3055 Activity.NonConfigurationInstances lastNonConfigurationInstances, IBinder assistToken) {
3056 ActivityClientRecord r = new ActivityClientRecord();
3057 r.token = token;
3058 r.assistToken = assistToken;
3059 r.ident = 0;
3060 r.intent = intent;
3061 r.state = state;
3062 r.parent = parent;
3063 r.embeddedID = id;
3064 r.activityInfo = activityInfo;
3065 r.lastNonConfigurationInstances = lastNonConfigurationInstances;
3066 if (localLOGV) {
3067 ComponentName compname = intent.getComponent();
3068 String name;
3069 if (compname != null) {
3070 name = compname.toShortString();
3071 } else {
3072 name = "(Intent " + intent + ").getComponent() returned null";
3073 }
3074 Slog.v(TAG, "Performing launch: action=" + intent.getAction()
3075 + ", comp=" + name
3076 + ", token=" + token);
3077 }
3078 // TODO(lifecycler): Can't switch to use #handleLaunchActivity() because it will try to
3079 // call #reportSizeConfigurations(), but the server might not know anything about the
3080 // activity if it was launched from LocalAcvitivyManager.
3081 return performLaunchActivity(r, null /* customIntent */);
3082 }
3083
3084 @UnsupportedAppUsage
3085 public final Activity getActivity(IBinder token) {
3086 final ActivityClientRecord activityRecord = mActivities.get(token);
3087 return activityRecord != null ? activityRecord.activity : null;
3088 }
3089
3090 @Override
3091 public ActivityClientRecord getActivityClient(IBinder token) {
3092 return mActivities.get(token);
3093 }
3094
3095 @VisibleForTesting(visibility = PACKAGE)
3096 public Configuration getConfiguration() {
3097 return mConfiguration;
3098 }
3099
3100 @Override
3101 public void updatePendingConfiguration(Configuration config) {
3102 synchronized (mResourcesManager) {
3103 if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(config)) {
3104 mPendingConfiguration = config;
3105 }
3106 }
3107 }
3108
3109 @Override
3110 public void updateProcessState(int processState, boolean fromIpc) {
3111 synchronized (mAppThread) {
3112 if (mLastProcessState == processState) {
3113 return;
3114 }
3115 mLastProcessState = processState;
3116 // Defer the top state for VM to avoid aggressive JIT compilation affecting activity
3117 // launch time.
3118 if (processState == ActivityManager.PROCESS_STATE_TOP
3119 && mNumLaunchingActivities.get() > 0) {
3120 mPendingProcessState = processState;
3121 mH.postDelayed(this::applyPendingProcessState, PENDING_TOP_PROCESS_STATE_TIMEOUT);
3122 } else {
3123 mPendingProcessState = PROCESS_STATE_UNKNOWN;
3124 updateVmProcessState(processState);
3125 }
3126 if (localLOGV) {
3127 Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
3128 + (fromIpc ? " (from ipc" : ""));
3129 }
3130 }
3131 }
3132
3133 /** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
3134 private void updateVmProcessState(int processState) {
3135 // TODO: Tune this since things like gmail sync are important background but not jank
3136 // perceptible.
3137 final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
3138 ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
3139 : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
3140 VMRuntime.getRuntime().updateProcessState(state);
3141 }
3142
3143 private void applyPendingProcessState() {
3144 synchronized (mAppThread) {
3145 if (mPendingProcessState == PROCESS_STATE_UNKNOWN) {
3146 return;
3147 }
3148 final int pendingState = mPendingProcessState;
3149 mPendingProcessState = PROCESS_STATE_UNKNOWN;
3150 // Only apply the pending state if the last state doesn't change.
3151 if (pendingState == mLastProcessState) {
3152 updateVmProcessState(pendingState);
3153 }
3154 }
3155 }
3156
3157 @Override
3158 public void countLaunchingActivities(int num) {
3159 mNumLaunchingActivities.getAndAdd(num);
3160 }
3161
3162 @UnsupportedAppUsage
3163 public final void sendActivityResult(
3164 IBinder token, String id, int requestCode,
3165 int resultCode, Intent data) {
3166 if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
3167 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
3168 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3169 list.add(new ResultInfo(id, requestCode, resultCode, data));
3170 final ClientTransaction clientTransaction = ClientTransaction.obtain(mAppThread, token);
3171 clientTransaction.addCallback(ActivityResultItem.obtain(list));
3172 try {
3173 mAppThread.scheduleTransaction(clientTransaction);
3174 } catch (RemoteException e) {
3175 // Local scheduling
3176 }
3177 }
3178
3179 @Override
3180 TransactionExecutor getTransactionExecutor() {
3181 return mTransactionExecutor;
3182 }
3183
3184 void sendMessage(int what, Object obj) {
3185 sendMessage(what, obj, 0, 0, false);
3186 }
3187
3188 private void sendMessage(int what, Object obj, int arg1) {
3189 sendMessage(what, obj, arg1, 0, false);
3190 }
3191
3192 private void sendMessage(int what, Object obj, int arg1, int arg2) {
3193 sendMessage(what, obj, arg1, arg2, false);
3194 }
3195
3196 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
3197 if (DEBUG_MESSAGES) {
3198 Slog.v(TAG,
3199 "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
3200 }
3201 Message msg = Message.obtain();
3202 msg.what = what;
3203 msg.obj = obj;
3204 msg.arg1 = arg1;
3205 msg.arg2 = arg2;
3206 if (async) {
3207 msg.setAsynchronous(true);
3208 }
3209 mH.sendMessage(msg);
3210 }
3211
3212 private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
3213 if (DEBUG_MESSAGES) Slog.v(
3214 TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
3215 "seq= " + seq);
3216 Message msg = Message.obtain();
3217 msg.what = what;
3218 SomeArgs args = SomeArgs.obtain();
3219 args.arg1 = obj;
3220 args.argi1 = arg1;
3221 args.argi2 = arg2;
3222 args.argi3 = seq;
3223 msg.obj = args;
3224 mH.sendMessage(msg);
3225 }
3226
3227 final void scheduleContextCleanup(ContextImpl context, String who,
3228 String what) {
3229 ContextCleanupInfo cci = new ContextCleanupInfo();
3230 cci.context = context;
3231 cci.who = who;
3232 cci.what = what;
3233 sendMessage(H.CLEAN_UP_CONTEXT, cci);
3234 }
3235
3236 /** Core implementation of activity launch. */
3237 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
3238 ActivityInfo aInfo = r.activityInfo;
3239 if (r.packageInfo == null) {
3240 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
3241 Context.CONTEXT_INCLUDE_CODE);
3242 }
3243
3244 ComponentName component = r.intent.getComponent();
3245 if (component == null) {
3246 component = r.intent.resolveActivity(
3247 mInitialApplication.getPackageManager());
3248 r.intent.setComponent(component);
3249 }
3250
3251 if (r.activityInfo.targetActivity != null) {
3252 component = new ComponentName(r.activityInfo.packageName,
3253 r.activityInfo.targetActivity);
3254 }
3255
3256 ContextImpl appContext = createBaseContextForActivity(r);
3257 Activity activity = null;
3258 try {
3259 java.lang.ClassLoader cl = appContext.getClassLoader();
3260 activity = mInstrumentation.newActivity(
3261 cl, component.getClassName(), r.intent);
3262 StrictMode.incrementExpectedActivityCount(activity.getClass());
3263 r.intent.setExtrasClassLoader(cl);
3264 r.intent.prepareToEnterProcess();
3265 if (r.state != null) {
3266 r.state.setClassLoader(cl);
3267 }
3268 } catch (Exception e) {
3269 if (!mInstrumentation.onException(activity, e)) {
3270 throw new RuntimeException(
3271 "Unable to instantiate activity " + component
3272 + ": " + e.toString(), e);
3273 }
3274 }
3275
3276 try {
3277 Application app = r.packageInfo.makeApplication(false, mInstrumentation);
3278
3279 if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
3280 if (localLOGV) Slog.v(
3281 TAG, r + ": app=" + app
3282 + ", appName=" + app.getPackageName()
3283 + ", pkg=" + r.packageInfo.getPackageName()
3284 + ", comp=" + r.intent.getComponent().toShortString()
3285 + ", dir=" + r.packageInfo.getAppDir());
3286
3287 if (activity != null) {
3288 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
3289 Configuration config = new Configuration(mCompatConfiguration);
3290 if (r.overrideConfig != null) {
3291 config.updateFrom(r.overrideConfig);
3292 }
3293 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
3294 + r.activityInfo.name + " with config " + config);
3295 Window window = null;
3296 if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
3297 window = r.mPendingRemoveWindow;
3298 r.mPendingRemoveWindow = null;
3299 r.mPendingRemoveWindowManager = null;
3300 }
3301
3302 // Activity resources must be initialized with the same loaders as the
3303 // application context.
3304 appContext.getResources().addLoaders(
3305 app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
3306
3307 appContext.setOuterContext(activity);
3308 activity.attach(appContext, this, getInstrumentation(), r.token,
3309 r.ident, app, r.intent, r.activityInfo, title, r.parent,
3310 r.embeddedID, r.lastNonConfigurationInstances, config,
3311 r.referrer, r.voiceInteractor, window, r.configCallback,
3312 r.assistToken);
3313
3314 if (customIntent != null) {
3315 activity.mIntent = customIntent;
3316 }
3317 r.lastNonConfigurationInstances = null;
3318 checkAndBlockForNetworkAccess();
3319 activity.mStartedActivity = false;
3320 int theme = r.activityInfo.getThemeResource();
3321 if (theme != 0) {
3322 activity.setTheme(theme);
3323 }
3324
3325 activity.mCalled = false;
3326 if (r.isPersistable()) {
3327 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
3328 } else {
3329 mInstrumentation.callActivityOnCreate(activity, r.state);
3330 }
3331 if (!activity.mCalled) {
3332 throw new SuperNotCalledException(
3333 "Activity " + r.intent.getComponent().toShortString() +
3334 " did not call through to super.onCreate()");
3335 }
3336 r.activity = activity;
3337 mLastReportedWindowingMode.put(activity.getActivityToken(),
3338 config.windowConfiguration.getWindowingMode());
3339 }
3340 r.setState(ON_CREATE);
3341
3342 // updatePendingActivityConfiguration() reads from mActivities to update
3343 // ActivityClientRecord which runs in a different thread. Protect modifications to
3344 // mActivities to avoid race.
3345 synchronized (mResourcesManager) {
3346 mActivities.put(r.token, r);
3347 }
3348
3349 } catch (SuperNotCalledException e) {
3350 throw e;
3351
3352 } catch (Exception e) {
3353 if (!mInstrumentation.onException(activity, e)) {
3354 throw new RuntimeException(
3355 "Unable to start activity " + component
3356 + ": " + e.toString(), e);
3357 }
3358 }
3359
3360 return activity;
3361 }
3362
3363 @Override
3364 public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {
3365 final ActivityClientRecord r = mActivities.get(token);
3366 final Activity activity = r.activity;
3367 if (r.activity == null) {
3368 // TODO(lifecycler): What do we do in this case?
3369 return;
3370 }
3371 if (!r.stopped) {
3372 throw new IllegalStateException("Can't start activity that is not stopped.");
3373 }
3374 if (r.activity.mFinished) {
3375 // TODO(lifecycler): How can this happen?
3376 return;
3377 }
3378
3379 unscheduleGcIdler();
3380
3381 // Start
3382 activity.performStart("handleStartActivity");
3383 r.setState(ON_START);
3384
3385 if (pendingActions == null) {
3386 // No more work to do.
3387 return;
3388 }
3389
3390 // Restore instance state
3391 if (pendingActions.shouldRestoreInstanceState()) {
3392 if (r.isPersistable()) {
3393 if (r.state != null || r.persistentState != null) {
3394 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
3395 r.persistentState);
3396 }
3397 } else if (r.state != null) {
3398 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
3399 }
3400 }
3401
3402 // Call postOnCreate()
3403 if (pendingActions.shouldCallOnPostCreate()) {
3404 activity.mCalled = false;
3405 if (r.isPersistable()) {
3406 mInstrumentation.callActivityOnPostCreate(activity, r.state,
3407 r.persistentState);
3408 } else {
3409 mInstrumentation.callActivityOnPostCreate(activity, r.state);
3410 }
3411 if (!activity.mCalled) {
3412 throw new SuperNotCalledException(
3413 "Activity " + r.intent.getComponent().toShortString()
3414 + " did not call through to super.onPostCreate()");
3415 }
3416 }
3417
3418 updateVisibility(r, true /* show */);
3419 mSomeActivitiesChanged = true;
3420 }
3421
3422 /**
3423 * Checks if {@link #mNetworkBlockSeq} is {@link #INVALID_PROC_STATE_SEQ} and if so, returns
3424 * immediately. Otherwise, makes a blocking call to ActivityManagerService to wait for the
3425 * network rules to get updated.
3426 */
3427 private void checkAndBlockForNetworkAccess() {
3428 synchronized (mNetworkPolicyLock) {
3429 if (mNetworkBlockSeq != INVALID_PROC_STATE_SEQ) {
3430 try {
3431 ActivityManager.getService().waitForNetworkStateUpdate(mNetworkBlockSeq);
3432 mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
3433 } catch (RemoteException ignored) {}
3434 }
3435 }
3436 }
3437
3438 private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
3439 final int displayId;
3440 try {
3441 displayId = ActivityTaskManager.getService().getDisplayId(r.token);
3442 } catch (RemoteException e) {
3443 throw e.rethrowFromSystemServer();
3444 }
3445
3446 ContextImpl appContext = ContextImpl.createActivityContext(
3447 this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
3448
3449 final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
3450 // For debugging purposes, if the activity's package name contains the value of
3451 // the "debug.use-second-display" system property as a substring, then show
3452 // its content on a secondary display if there is one.
3453 String pkgName = SystemProperties.get("debug.second-display.pkg");
3454 if (pkgName != null && !pkgName.isEmpty()
3455 && r.packageInfo.mPackageName.contains(pkgName)) {
3456 for (int id : dm.getDisplayIds()) {
3457 if (id != Display.DEFAULT_DISPLAY) {
3458 Display display =
3459 dm.getCompatibleDisplay(id, appContext.getResources());
3460 appContext = (ContextImpl) appContext.createDisplayContext(display);
3461 break;
3462 }
3463 }
3464 }
3465 return appContext;
3466 }
3467
3468 /**
3469 * Extended implementation of activity launch. Used when server requests a launch or relaunch.
3470 */
3471 @Override
3472 public Activity handleLaunchActivity(ActivityClientRecord r,
3473 PendingTransactionActions pendingActions, Intent customIntent) {
3474 // If we are getting ready to gc after going to the background, well
3475 // we are back active so skip it.
3476 unscheduleGcIdler();
3477 mSomeActivitiesChanged = true;
3478
3479 if (r.profilerInfo != null) {
3480 mProfiler.setProfiler(r.profilerInfo);
3481 mProfiler.startProfiling();
3482 }
3483
3484 // Make sure we are running with the most recent config.
3485 handleConfigurationChanged(null, null);
3486
3487 if (localLOGV) Slog.v(
3488 TAG, "Handling launch of " + r);
3489
3490 // Initialize before creating the activity
3491 if (!ThreadedRenderer.sRendererDisabled
3492 && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
3493 HardwareRenderer.preload();
3494 }
3495 WindowManagerGlobal.initialize();
3496
3497 // Hint the GraphicsEnvironment that an activity is launching on the process.
3498 GraphicsEnvironment.hintActivityLaunch();
3499
3500 final Activity a = performLaunchActivity(r, customIntent);
3501
3502 if (a != null) {
3503 r.createdConfig = new Configuration(mConfiguration);
3504 reportSizeConfigurations(r);
3505 if (!r.activity.mFinished && pendingActions != null) {
3506 pendingActions.setOldState(r.state);
3507 pendingActions.setRestoreInstanceState(true);
3508 pendingActions.setCallOnPostCreate(true);
3509 }
3510 } else {
3511 // If there was an error, for any reason, tell the activity manager to stop us.
3512 try {
3513 ActivityTaskManager.getService()
3514 .finishActivity(r.token, Activity.RESULT_CANCELED, null,
3515 Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
3516 } catch (RemoteException ex) {
3517 throw ex.rethrowFromSystemServer();
3518 }
3519 }
3520
3521 return a;
3522 }
3523
3524 private void reportSizeConfigurations(ActivityClientRecord r) {
3525 if (mActivitiesToBeDestroyed.containsKey(r.token)) {
3526 // Size configurations of a destroyed activity is meaningless.
3527 return;
3528 }
3529 Configuration[] configurations = r.activity.getResources().getSizeConfigurations();
3530 if (configurations == null) {
3531 return;
3532 }
3533 SparseIntArray horizontal = new SparseIntArray();
3534 SparseIntArray vertical = new SparseIntArray();
3535 SparseIntArray smallest = new SparseIntArray();
3536 for (int i = configurations.length - 1; i >= 0; i--) {
3537 Configuration config = configurations[i];
3538 if (config.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
3539 vertical.put(config.screenHeightDp, 0);
3540 }
3541 if (config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
3542 horizontal.put(config.screenWidthDp, 0);
3543 }
3544 if (config.smallestScreenWidthDp != Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
3545 smallest.put(config.smallestScreenWidthDp, 0);
3546 }
3547 }
3548 try {
3549 ActivityTaskManager.getService().reportSizeConfigurations(r.token,
3550 horizontal.copyKeys(), vertical.copyKeys(), smallest.copyKeys());
3551 } catch (RemoteException ex) {
3552 throw ex.rethrowFromSystemServer();
3553 }
3554 }
3555
3556 private void deliverNewIntents(ActivityClientRecord r, List<ReferrerIntent> intents) {
3557 final int N = intents.size();
3558 for (int i=0; i<N; i++) {
3559 ReferrerIntent intent = intents.get(i);
3560 intent.setExtrasClassLoader(r.activity.getClassLoader());
3561 intent.prepareToEnterProcess();
3562 r.activity.mFragments.noteStateNotSaved();
3563 mInstrumentation.callActivityOnNewIntent(r.activity, intent);
3564 }
3565 }
3566
3567 @Override
3568 public void handleNewIntent(IBinder token, List<ReferrerIntent> intents) {
3569 final ActivityClientRecord r = mActivities.get(token);
3570 if (r == null) {
3571 return;
3572 }
3573
3574 checkAndBlockForNetworkAccess();
3575 deliverNewIntents(r, intents);
3576 }
3577
3578 public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
3579 // Filling for autofill has a few differences:
3580 // - it does not need an AssistContent
3581 // - it does not call onProvideAssistData()
3582 // - it needs an IAutoFillCallback
3583 boolean forAutofill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTOFILL;
3584
3585 // TODO: decide if lastSessionId logic applies to autofill sessions
3586 if (mLastSessionId != cmd.sessionId) {
3587 // Clear the existing structures
3588 mLastSessionId = cmd.sessionId;
3589 for (int i = mLastAssistStructures.size() - 1; i >= 0; i--) {
3590 AssistStructure structure = mLastAssistStructures.get(i).get();
3591 if (structure != null) {
3592 structure.clearSendChannel();
3593 }
3594 mLastAssistStructures.remove(i);
3595 }
3596 }
3597
3598 Bundle data = new Bundle();
3599 AssistStructure structure = null;
3600 AssistContent content = forAutofill ? null : new AssistContent();
3601 final long startTime = SystemClock.uptimeMillis();
3602 ActivityClientRecord r = mActivities.get(cmd.activityToken);
3603 Uri referrer = null;
3604 if (r != null) {
3605 if (!forAutofill) {
3606 r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
3607 r.activity.onProvideAssistData(data);
3608 referrer = r.activity.onProvideReferrer();
3609 }
3610 if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) {
3611 structure = new AssistStructure(r.activity, forAutofill, cmd.flags);
3612 Intent activityIntent = r.activity.getIntent();
3613 boolean notSecure = r.window == null ||
3614 (r.window.getAttributes().flags
3615 & WindowManager.LayoutParams.FLAG_SECURE) == 0;
3616 if (activityIntent != null && notSecure) {
3617 if (!forAutofill) {
3618 Intent intent = new Intent(activityIntent);
3619 intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3620 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
3621 intent.removeUnsafeExtras();
3622 content.setDefaultIntent(intent);
3623 }
3624 } else {
3625 if (!forAutofill) {
3626 content.setDefaultIntent(new Intent());
3627 }
3628 }
3629 if (!forAutofill) {
3630 r.activity.onProvideAssistContent(content);
3631 }
3632 }
3633
3634 }
3635 if (structure == null) {
3636 structure = new AssistStructure();
3637 }
3638
3639 // TODO: decide if lastSessionId logic applies to autofill sessions
3640
3641 structure.setAcquisitionStartTime(startTime);
3642 structure.setAcquisitionEndTime(SystemClock.uptimeMillis());
3643
3644 mLastAssistStructures.add(new WeakReference<>(structure));
3645 IActivityTaskManager mgr = ActivityTaskManager.getService();
3646 try {
3647 mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
3648 } catch (RemoteException e) {
3649 throw e.rethrowFromSystemServer();
3650 }
3651 }
3652
3653 /** Fetches the user actions for the corresponding activity */
3654 private void handleRequestDirectActions(@NonNull IBinder activityToken,
3655 @NonNull IVoiceInteractor interactor, @NonNull CancellationSignal cancellationSignal,
3656 @NonNull RemoteCallback callback) {
3657 final ActivityClientRecord r = mActivities.get(activityToken);
3658 if (r == null) {
3659 Log.w(TAG, "requestDirectActions(): no activity for " + activityToken);
3660 callback.sendResult(null);
3661 return;
3662 }
3663 final int lifecycleState = r.getLifecycleState();
3664 if (lifecycleState < ON_START || lifecycleState >= ON_STOP) {
3665 Log.w(TAG, "requestDirectActions(" + r + "): wrong lifecycle: " + lifecycleState);
3666 callback.sendResult(null);
3667 return;
3668 }
3669 if (r.activity.mVoiceInteractor == null
3670 || r.activity.mVoiceInteractor.mInteractor.asBinder()
3671 != interactor.asBinder()) {
3672 if (r.activity.mVoiceInteractor != null) {
3673 r.activity.mVoiceInteractor.destroy();
3674 }
3675 r.activity.mVoiceInteractor = new VoiceInteractor(interactor, r.activity,
3676 r.activity, Looper.myLooper());
3677 }
3678 r.activity.onGetDirectActions(cancellationSignal, (actions) -> {
3679 Objects.requireNonNull(actions);
3680 Preconditions.checkCollectionElementsNotNull(actions, "actions");
3681 if (!actions.isEmpty()) {
3682 final int actionCount = actions.size();
3683 for (int i = 0; i < actionCount; i++) {
3684 final DirectAction action = actions.get(i);
3685 action.setSource(r.activity.getTaskId(), r.activity.getAssistToken());
3686 }
3687 final Bundle result = new Bundle();
3688 result.putParcelable(DirectAction.KEY_ACTIONS_LIST,
3689 new ParceledListSlice<>(actions));
3690 callback.sendResult(result);
3691 } else {
3692 callback.sendResult(null);
3693 }
3694 });
3695 }
3696
3697 /** Performs an actions in the corresponding activity */
3698 private void handlePerformDirectAction(@NonNull IBinder activityToken,
3699 @NonNull String actionId, @Nullable Bundle arguments,
3700 @NonNull CancellationSignal cancellationSignal,
3701 @NonNull RemoteCallback resultCallback) {
3702 final ActivityClientRecord r = mActivities.get(activityToken);
3703 if (r != null) {
3704 final int lifecycleState = r.getLifecycleState();
3705 if (lifecycleState < ON_START || lifecycleState >= ON_STOP) {
3706 resultCallback.sendResult(null);
3707 return;
3708 }
3709 final Bundle nonNullArguments = (arguments != null) ? arguments : Bundle.EMPTY;
3710 r.activity.onPerformDirectAction(actionId, nonNullArguments, cancellationSignal,
3711 resultCallback::sendResult);
3712 } else {
3713 resultCallback.sendResult(null);
3714 }
3715 }
3716
3717 public void handleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
3718 ActivityClientRecord r = mActivities.get(token);
3719 if (r != null) {
3720 r.activity.onTranslucentConversionComplete(drawComplete);
3721 }
3722 }
3723
3724 public void onNewActivityOptions(IBinder token, ActivityOptions options) {
3725 ActivityClientRecord r = mActivities.get(token);
3726 if (r != null) {
3727 r.activity.onNewActivityOptions(options);
3728 }
3729 }
3730
3731 public void handleInstallProvider(ProviderInfo info) {
3732 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
3733 try {
3734 installContentProviders(mInitialApplication, Arrays.asList(info));
3735 } finally {
3736 StrictMode.setThreadPolicy(oldPolicy);
3737 }
3738 }
3739
3740 private void handleEnterAnimationComplete(IBinder token) {
3741 ActivityClientRecord r = mActivities.get(token);
3742 if (r != null) {
3743 r.activity.dispatchEnterAnimationComplete();
3744 }
3745 }
3746
3747 private void handleStartBinderTracking() {
3748 Binder.enableTracing();
3749 }
3750
3751 private void handleStopBinderTrackingAndDump(ParcelFileDescriptor fd) {
3752 try {
3753 Binder.disableTracing();
3754 Binder.getTransactionTracker().writeTracesToFile(fd);
3755 } finally {
3756 IoUtils.closeQuietly(fd);
3757 Binder.getTransactionTracker().clearTraces();
3758 }
3759 }
3760
3761 @Override
3762 public void handlePictureInPictureRequested(IBinder token) {
3763 final ActivityClientRecord r = mActivities.get(token);
3764 if (r == null) {
3765 Log.w(TAG, "Activity to request PIP to no longer exists");
3766 return;
3767 }
3768
3769 final boolean receivedByApp = r.activity.onPictureInPictureRequested();
3770 if (!receivedByApp) {
3771 // Previous recommendation was for apps to enter picture-in-picture in
3772 // onUserLeavingHint() for cases such as the app being put into the background. For
3773 // backwards compatibility with apps that are not using the newer
3774 // onPictureInPictureRequested() callback, we schedule the life cycle events needed to
3775 // trigger onUserLeavingHint(), then we return the activity to its previous state.
3776 schedulePauseWithUserLeaveHintAndReturnToCurrentState(r);
3777 }
3778 }
3779
3780 /**
3781 * Cycle activity through onPause and onUserLeaveHint so that PIP is entered if supported, then
3782 * return to its previous state. This allows activities that rely on onUserLeaveHint instead of
3783 * onPictureInPictureRequested to enter picture-in-picture.
3784 */
3785 private void schedulePauseWithUserLeaveHintAndReturnToCurrentState(ActivityClientRecord r) {
3786 final int prevState = r.getLifecycleState();
3787 if (prevState != ON_RESUME && prevState != ON_PAUSE) {
3788 return;
3789 }
3790
3791 switch (prevState) {
3792 case ON_RESUME:
3793 // Schedule a PAUSE then return to RESUME.
3794 schedulePauseWithUserLeavingHint(r);
3795 scheduleResume(r);
3796 break;
3797 case ON_PAUSE:
3798 // Schedule a RESUME then return to PAUSE.
3799 scheduleResume(r);
3800 schedulePauseWithUserLeavingHint(r);
3801 break;
3802 }
3803 }
3804
3805 private void schedulePauseWithUserLeavingHint(ActivityClientRecord r) {
3806 final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
3807 transaction.setLifecycleStateRequest(PauseActivityItem.obtain(r.activity.isFinishing(),
3808 /* userLeaving */ true, r.activity.mConfigChangeFlags, /* dontReport */ false));
3809 executeTransaction(transaction);
3810 }
3811
3812 private void scheduleResume(ActivityClientRecord r) {
3813 final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
3814 transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(/* isForward */ false));
3815 executeTransaction(transaction);
3816 }
3817
3818 private void handleLocalVoiceInteractionStarted(IBinder token, IVoiceInteractor interactor) {
3819 final ActivityClientRecord r = mActivities.get(token);
3820 if (r != null) {
3821 r.voiceInteractor = interactor;
3822 r.activity.setVoiceInteractor(interactor);
3823 if (interactor == null) {
3824 r.activity.onLocalVoiceInteractionStopped();
3825 } else {
3826 r.activity.onLocalVoiceInteractionStarted();
3827 }
3828 }
3829 }
3830
3831 private static boolean attemptAttachAgent(String agent, ClassLoader classLoader) {
3832 try {
3833 VMDebug.attachAgent(agent, classLoader);
3834 return true;
3835 } catch (IOException e) {
3836 Slog.e(TAG, "Attaching agent with " + classLoader + " failed: " + agent);
3837 return false;
3838 }
3839 }
3840
3841 static void handleAttachAgent(String agent, LoadedApk loadedApk) {
3842 ClassLoader classLoader = loadedApk != null ? loadedApk.getClassLoader() : null;
3843 if (attemptAttachAgent(agent, classLoader)) {
3844 return;
3845 }
3846 if (classLoader != null) {
3847 attemptAttachAgent(agent, null);
3848 }
3849 }
3850
3851 static void handleAttachStartupAgents(String dataDir) {
3852 try {
3853 Path code_cache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
3854 if (!Files.exists(code_cache)) {
3855 return;
3856 }
3857 Path startup_path = code_cache.resolve("startup_agents");
3858 if (Files.exists(startup_path)) {
3859 for (Path p : Files.newDirectoryStream(startup_path)) {
3860 handleAttachAgent(
3861 p.toAbsolutePath().toString()
3862 + "="
3863 + dataDir,
3864 null);
3865 }
3866 }
3867 } catch (Exception e) {
3868 // Ignored.
3869 }
3870 }
3871
3872 private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
3873
3874 /**
3875 * Return the Intent that's currently being handled by a
3876 * BroadcastReceiver on this thread, or null if none.
3877 * @hide
3878 */
3879 public static Intent getIntentBeingBroadcast() {
3880 return sCurrentBroadcastIntent.get();
3881 }
3882
3883 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
3884 private void handleReceiver(ReceiverData data) {
3885 // If we are getting ready to gc after going to the background, well
3886 // we are back active so skip it.
3887 unscheduleGcIdler();
3888
3889 String component = data.intent.getComponent().getClassName();
3890
3891 LoadedApk packageInfo = getPackageInfoNoCheck(
3892 data.info.applicationInfo, data.compatInfo);
3893
3894 IActivityManager mgr = ActivityManager.getService();
3895
3896 Application app;
3897 BroadcastReceiver receiver;
3898 ContextImpl context;
3899 try {
3900 app = packageInfo.makeApplication(false, mInstrumentation);
3901 context = (ContextImpl) app.getBaseContext();
3902 if (data.info.splitName != null) {
3903 context = (ContextImpl) context.createContextForSplit(data.info.splitName);
3904 }
3905 java.lang.ClassLoader cl = context.getClassLoader();
3906 data.intent.setExtrasClassLoader(cl);
3907 data.intent.prepareToEnterProcess();
3908 data.setExtrasClassLoader(cl);
3909 receiver = packageInfo.getAppFactory()
3910 .instantiateReceiver(cl, data.info.name, data.intent);
3911 } catch (Exception e) {
3912 if (DEBUG_BROADCAST) Slog.i(TAG,
3913 "Finishing failed broadcast to " + data.intent.getComponent());
3914 data.sendFinished(mgr);
3915 throw new RuntimeException(
3916 "Unable to instantiate receiver " + component
3917 + ": " + e.toString(), e);
3918 }
3919
3920 try {
3921 if (localLOGV) Slog.v(
3922 TAG, "Performing receive of " + data.intent
3923 + ": app=" + app
3924 + ", appName=" + app.getPackageName()
3925 + ", pkg=" + packageInfo.getPackageName()
3926 + ", comp=" + data.intent.getComponent().toShortString()
3927 + ", dir=" + packageInfo.getAppDir());
3928
3929 sCurrentBroadcastIntent.set(data.intent);
3930 receiver.setPendingResult(data);
3931 receiver.onReceive(context.getReceiverRestrictedContext(),
3932 data.intent);
3933 } catch (Exception e) {
3934 if (DEBUG_BROADCAST) Slog.i(TAG,
3935 "Finishing failed broadcast to " + data.intent.getComponent());
3936 data.sendFinished(mgr);
3937 if (!mInstrumentation.onException(receiver, e)) {
3938 throw new RuntimeException(
3939 "Unable to start receiver " + component
3940 + ": " + e.toString(), e);
3941 }
3942 } finally {
3943 sCurrentBroadcastIntent.set(null);
3944 }
3945
3946 if (receiver.getPendingResult() != null) {
3947 data.finish();
3948 }
3949 }
3950
3951 // Instantiate a BackupAgent and tell it that it's alive
3952 private void handleCreateBackupAgent(CreateBackupAgentData data) {
3953 if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
3954
3955 // Sanity check the requested target package's uid against ours
3956 try {
3957 PackageInfo requestedPackage = getPackageManager().getPackageInfo(
3958 data.appInfo.packageName, 0, UserHandle.myUserId());
3959 if (requestedPackage.applicationInfo.uid != Process.myUid()) {
3960 Slog.w(TAG, "Asked to instantiate non-matching package "
3961 + data.appInfo.packageName);
3962 return;
3963 }
3964 } catch (RemoteException e) {
3965 throw e.rethrowFromSystemServer();
3966 }
3967
3968 // no longer idle; we have backup work to do
3969 unscheduleGcIdler();
3970
3971 // instantiate the BackupAgent class named in the manifest
3972 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
3973 String packageName = packageInfo.mPackageName;
3974 if (packageName == null) {
3975 Slog.d(TAG, "Asked to create backup agent for nonexistent package");
3976 return;
3977 }
3978
3979 String classname = data.appInfo.backupAgentName;
3980 // full backup operation but no app-supplied agent? use the default implementation
3981 if (classname == null && (data.backupMode == ApplicationThreadConstants.BACKUP_MODE_FULL
3982 || data.backupMode == ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL)) {
3983 classname = "android.app.backup.FullBackupAgent";
3984 }
3985
3986 try {
3987 IBinder binder = null;
3988 ArrayMap<String, BackupAgent> backupAgents = getBackupAgentsForUser(data.userId);
3989 BackupAgent agent = backupAgents.get(packageName);
3990 if (agent != null) {
3991 // reusing the existing instance
3992 if (DEBUG_BACKUP) {
3993 Slog.v(TAG, "Reusing existing agent instance");
3994 }
3995 binder = agent.onBind();
3996 } else {
3997 try {
3998 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
3999
4000 java.lang.ClassLoader cl = packageInfo.getClassLoader();
4001 agent = (BackupAgent) cl.loadClass(classname).newInstance();
4002
4003 // set up the agent's context
4004 ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
4005 context.setOuterContext(agent);
4006 agent.attach(context);
4007
4008 agent.onCreate(UserHandle.of(data.userId));
4009 binder = agent.onBind();
4010 backupAgents.put(packageName, agent);
4011 } catch (Exception e) {
4012 // If this is during restore, fail silently; otherwise go
4013 // ahead and let the user see the crash.
4014 Slog.e(TAG, "Agent threw during creation: " + e);
4015 if (data.backupMode != ApplicationThreadConstants.BACKUP_MODE_RESTORE
4016 && data.backupMode !=
4017 ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL) {
4018 throw e;
4019 }
4020 // falling through with 'binder' still null
4021 }
4022 }
4023
4024 // tell the OS that we're live now
4025 try {
4026 ActivityManager.getService().backupAgentCreated(packageName, binder, data.userId);
4027 } catch (RemoteException e) {
4028 throw e.rethrowFromSystemServer();
4029 }
4030 } catch (Exception e) {
4031 throw new RuntimeException("Unable to create BackupAgent "
4032 + classname + ": " + e.toString(), e);
4033 }
4034 }
4035
4036 // Tear down a BackupAgent
4037 private void handleDestroyBackupAgent(CreateBackupAgentData data) {
4038 if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
4039
4040 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
4041 String packageName = packageInfo.mPackageName;
4042 ArrayMap<String, BackupAgent> backupAgents = getBackupAgentsForUser(data.userId);
4043 BackupAgent agent = backupAgents.get(packageName);
4044 if (agent != null) {
4045 try {
4046 agent.onDestroy();
4047 } catch (Exception e) {
4048 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
4049 e.printStackTrace();
4050 }
4051 backupAgents.remove(packageName);
4052 } else {
4053 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
4054 }
4055 }
4056
4057 private ArrayMap<String, BackupAgent> getBackupAgentsForUser(int userId) {
4058 ArrayMap<String, BackupAgent> backupAgents = mBackupAgentsByUser.get(userId);
4059 if (backupAgents == null) {
4060 backupAgents = new ArrayMap<>();
4061 mBackupAgentsByUser.put(userId, backupAgents);
4062 }
4063 return backupAgents;
4064 }
4065
4066 @UnsupportedAppUsage
4067 private void handleCreateService(CreateServiceData data) {
4068 // If we are getting ready to gc after going to the background, well
4069 // we are back active so skip it.
4070 unscheduleGcIdler();
4071
4072 LoadedApk packageInfo = getPackageInfoNoCheck(
4073 data.info.applicationInfo, data.compatInfo);
4074 Service service = null;
4075 try {
4076 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
4077
4078 ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
4079 Application app = packageInfo.makeApplication(false, mInstrumentation);
4080 java.lang.ClassLoader cl = packageInfo.getClassLoader();
4081 service = packageInfo.getAppFactory()
4082 .instantiateService(cl, data.info.name, data.intent);
4083 // Service resources must be initialized with the same loaders as the application
4084 // context.
4085 context.getResources().addLoaders(
4086 app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
4087
4088 context.setOuterContext(service);
4089 service.attach(context, this, data.info.name, data.token, app,
4090 ActivityManager.getService());
4091 service.onCreate();
4092 mServices.put(data.token, service);
4093 try {
4094 ActivityManager.getService().serviceDoneExecuting(
4095 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
4096 } catch (RemoteException e) {
4097 throw e.rethrowFromSystemServer();
4098 }
4099 } catch (Exception e) {
4100 if (!mInstrumentation.onException(service, e)) {
4101 throw new RuntimeException(
4102 "Unable to create service " + data.info.name
4103 + ": " + e.toString(), e);
4104 }
4105 }
4106 }
4107
4108 private void handleBindService(BindServiceData data) {
4109 Service s = mServices.get(data.token);
4110 if (DEBUG_SERVICE)
4111 Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
4112 if (s != null) {
4113 try {
4114 data.intent.setExtrasClassLoader(s.getClassLoader());
4115 data.intent.prepareToEnterProcess();
4116 try {
4117 if (!data.rebind) {
4118 IBinder binder = s.onBind(data.intent);
4119 ActivityManager.getService().publishService(
4120 data.token, data.intent, binder);
4121 } else {
4122 s.onRebind(data.intent);
4123 ActivityManager.getService().serviceDoneExecuting(
4124 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
4125 }
4126 } catch (RemoteException ex) {
4127 throw ex.rethrowFromSystemServer();
4128 }
4129 } catch (Exception e) {
4130 if (!mInstrumentation.onException(s, e)) {
4131 throw new RuntimeException(
4132 "Unable to bind to service " + s
4133 + " with " + data.intent + ": " + e.toString(), e);
4134 }
4135 }
4136 }
4137 }
4138
4139 private void handleUnbindService(BindServiceData data) {
4140 Service s = mServices.get(data.token);
4141 if (s != null) {
4142 try {
4143 data.intent.setExtrasClassLoader(s.getClassLoader());
4144 data.intent.prepareToEnterProcess();
4145 boolean doRebind = s.onUnbind(data.intent);
4146 try {
4147 if (doRebind) {
4148 ActivityManager.getService().unbindFinished(
4149 data.token, data.intent, doRebind);
4150 } else {
4151 ActivityManager.getService().serviceDoneExecuting(
4152 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
4153 }
4154 } catch (RemoteException ex) {
4155 throw ex.rethrowFromSystemServer();
4156 }
4157 } catch (Exception e) {
4158 if (!mInstrumentation.onException(s, e)) {
4159 throw new RuntimeException(
4160 "Unable to unbind to service " + s
4161 + " with " + data.intent + ": " + e.toString(), e);
4162 }
4163 }
4164 }
4165 }
4166
4167 private void handleDumpService(DumpComponentInfo info) {
4168 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
4169 try {
4170 Service s = mServices.get(info.token);
4171 if (s != null) {
4172 PrintWriter pw = new FastPrintWriter(new FileOutputStream(
4173 info.fd.getFileDescriptor()));
4174 s.dump(info.fd.getFileDescriptor(), pw, info.args);
4175 pw.flush();
4176 }
4177 } finally {
4178 IoUtils.closeQuietly(info.fd);
4179 StrictMode.setThreadPolicy(oldPolicy);
4180 }
4181 }
4182
4183 private void handleDumpActivity(DumpComponentInfo info) {
4184 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
4185 try {
4186 ActivityClientRecord r = mActivities.get(info.token);
4187 if (r != null && r.activity != null) {
4188 PrintWriter pw = new FastPrintWriter(new FileOutputStream(
4189 info.fd.getFileDescriptor()));
4190 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
4191 pw.flush();
4192 }
4193 } finally {
4194 IoUtils.closeQuietly(info.fd);
4195 StrictMode.setThreadPolicy(oldPolicy);
4196 }
4197 }
4198
4199 private void handleDumpProvider(DumpComponentInfo info) {
4200 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
4201 try {
4202 ProviderClientRecord r = mLocalProviders.get(info.token);
4203 if (r != null && r.mLocalProvider != null) {
4204 PrintWriter pw = new FastPrintWriter(new FileOutputStream(
4205 info.fd.getFileDescriptor()));
4206 r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
4207 pw.flush();
4208 }
4209 } finally {
4210 IoUtils.closeQuietly(info.fd);
4211 StrictMode.setThreadPolicy(oldPolicy);
4212 }
4213 }
4214
4215 private void handleServiceArgs(ServiceArgsData data) {
4216 Service s = mServices.get(data.token);
4217 if (s != null) {
4218 try {
4219 if (data.args != null) {
4220 data.args.setExtrasClassLoader(s.getClassLoader());
4221 data.args.prepareToEnterProcess();
4222 }
4223 int res;
4224 if (!data.taskRemoved) {
4225 res = s.onStartCommand(data.args, data.flags, data.startId);
4226 } else {
4227 s.onTaskRemoved(data.args);
4228 res = Service.START_TASK_REMOVED_COMPLETE;
4229 }
4230
4231 QueuedWork.waitToFinish();
4232
4233 try {
4234 ActivityManager.getService().serviceDoneExecuting(
4235 data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
4236 } catch (RemoteException e) {
4237 throw e.rethrowFromSystemServer();
4238 }
4239 } catch (Exception e) {
4240 if (!mInstrumentation.onException(s, e)) {
4241 throw new RuntimeException(
4242 "Unable to start service " + s
4243 + " with " + data.args + ": " + e.toString(), e);
4244 }
4245 }
4246 }
4247 }
4248
4249 private void handleStopService(IBinder token) {
4250 Service s = mServices.remove(token);
4251 if (s != null) {
4252 try {
4253 if (localLOGV) Slog.v(TAG, "Destroying service " + s);
4254 s.onDestroy();
4255 s.detachAndCleanUp();
4256 Context context = s.getBaseContext();
4257 if (context instanceof ContextImpl) {
4258 final String who = s.getClassName();
4259 ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
4260 }
4261
4262 QueuedWork.waitToFinish();
4263
4264 try {
4265 ActivityManager.getService().serviceDoneExecuting(
4266 token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
4267 } catch (RemoteException e) {
4268 throw e.rethrowFromSystemServer();
4269 }
4270 } catch (Exception e) {
4271 if (!mInstrumentation.onException(s, e)) {
4272 throw new RuntimeException(
4273 "Unable to stop service " + s
4274 + ": " + e.toString(), e);
4275 }
4276 Slog.i(TAG, "handleStopService: exception for " + token, e);
4277 }
4278 } else {
4279 Slog.i(TAG, "handleStopService: token=" + token + " not found.");
4280 }
4281 //Slog.i(TAG, "Running services: " + mServices);
4282 }
4283
4284 /**
4285 * Resume the activity.
4286 * @param token Target activity token.
4287 * @param finalStateRequest Flag indicating if this is part of final state resolution for a
4288 * transaction.
4289 * @param reason Reason for performing the action.
4290 *
4291 * @return The {@link ActivityClientRecord} that was resumed, {@code null} otherwise.
4292 */
4293 @VisibleForTesting
4294 public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
4295 String reason) {
4296 final ActivityClientRecord r = mActivities.get(token);
4297 if (localLOGV) {
4298 Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
4299 }
4300 if (r == null || r.activity.mFinished) {
4301 return null;
4302 }
4303 if (r.getLifecycleState() == ON_RESUME) {
4304 if (!finalStateRequest) {
4305 final RuntimeException e = new IllegalStateException(
4306 "Trying to resume activity which is already resumed");
4307 Slog.e(TAG, e.getMessage(), e);
4308 Slog.e(TAG, r.getStateString());
4309 // TODO(lifecycler): A double resume request is possible when an activity
4310 // receives two consequent transactions with relaunch requests and "resumed"
4311 // final state requests and the second relaunch is omitted. We still try to
4312 // handle two resume requests for the final state. For cases other than this
4313 // one, we don't expect it to happen.
4314 }
4315 return null;
4316 }
4317 if (finalStateRequest) {
4318 r.hideForNow = false;
4319 r.activity.mStartedActivity = false;
4320 }
4321 try {
4322 r.activity.onStateNotSaved();
4323 r.activity.mFragments.noteStateNotSaved();
4324 checkAndBlockForNetworkAccess();
4325 if (r.pendingIntents != null) {
4326 deliverNewIntents(r, r.pendingIntents);
4327 r.pendingIntents = null;
4328 }
4329 if (r.pendingResults != null) {
4330 deliverResults(r, r.pendingResults, reason);
4331 r.pendingResults = null;
4332 }
4333 r.activity.performResume(r.startsNotResumed, reason);
4334
4335 r.state = null;
4336 r.persistentState = null;
4337 r.setState(ON_RESUME);
4338
4339 reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
4340 } catch (Exception e) {
4341 if (!mInstrumentation.onException(r.activity, e)) {
4342 throw new RuntimeException("Unable to resume activity "
4343 + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
4344 }
4345 }
4346 return r;
4347 }
4348
4349 static final void cleanUpPendingRemoveWindows(ActivityClientRecord r, boolean force) {
4350 if (r.mPreserveWindow && !force) {
4351 return;
4352 }
4353 if (r.mPendingRemoveWindow != null) {
4354 r.mPendingRemoveWindowManager.removeViewImmediate(
4355 r.mPendingRemoveWindow.getDecorView());
4356 IBinder wtoken = r.mPendingRemoveWindow.getDecorView().getWindowToken();
4357 if (wtoken != null) {
4358 WindowManagerGlobal.getInstance().closeAll(wtoken,
4359 r.activity.getClass().getName(), "Activity");
4360 }
4361 }
4362 r.mPendingRemoveWindow = null;
4363 r.mPendingRemoveWindowManager = null;
4364 }
4365
4366 @Override
4367 public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
4368 String reason) {
4369 // If we are getting ready to gc after going to the background, well
4370 // we are back active so skip it.
4371 unscheduleGcIdler();
4372 mSomeActivitiesChanged = true;
4373
4374 // TODO Push resumeArgs into the activity for consideration
4375 final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
4376 if (r == null) {
4377 // We didn't actually resume the activity, so skipping any follow-up actions.
4378 return;
4379 }
4380 if (mActivitiesToBeDestroyed.containsKey(token)) {
4381 // Although the activity is resumed, it is going to be destroyed. So the following
4382 // UI operations are unnecessary and also prevents exception because its token may
4383 // be gone that window manager cannot recognize it. All necessary cleanup actions
4384 // performed below will be done while handling destruction.
4385 return;
4386 }
4387
4388 final Activity a = r.activity;
4389
4390 if (localLOGV) {
4391 Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
4392 + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
4393 }
4394
4395 final int forwardBit = isForward
4396 ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
4397
4398 // If the window hasn't yet been added to the window manager,
4399 // and this guy didn't finish itself or start another activity,
4400 // then go ahead and add the window.
4401 boolean willBeVisible = !a.mStartedActivity;
4402 if (!willBeVisible) {
4403 try {
4404 willBeVisible = ActivityTaskManager.getService().willActivityBeVisible(
4405 a.getActivityToken());
4406 } catch (RemoteException e) {
4407 throw e.rethrowFromSystemServer();
4408 }
4409 }
4410 if (r.window == null && !a.mFinished && willBeVisible) {
4411 r.window = r.activity.getWindow();
4412 View decor = r.window.getDecorView();
4413 decor.setVisibility(View.INVISIBLE);
4414 ViewManager wm = a.getWindowManager();
4415 WindowManager.LayoutParams l = r.window.getAttributes();
4416 a.mDecor = decor;
4417 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
4418 l.softInputMode |= forwardBit;
4419 if (r.mPreserveWindow) {
4420 a.mWindowAdded = true;
4421 r.mPreserveWindow = false;
4422 // Normally the ViewRoot sets up callbacks with the Activity
4423 // in addView->ViewRootImpl#setView. If we are instead reusing
4424 // the decor view we have to notify the view root that the
4425 // callbacks may have changed.
4426 ViewRootImpl impl = decor.getViewRootImpl();
4427 if (impl != null) {
4428 impl.notifyChildRebuilt();
4429 }
4430 }
4431 if (a.mVisibleFromClient) {
4432 if (!a.mWindowAdded) {
4433 a.mWindowAdded = true;
4434 wm.addView(decor, l);
4435 } else {
4436 // The activity will get a callback for this {@link LayoutParams} change
4437 // earlier. However, at that time the decor will not be set (this is set
4438 // in this method), so no action will be taken. This call ensures the
4439 // callback occurs with the decor set.
4440 a.onWindowAttributesChanged(l);
4441 }
4442 }
4443
4444 // If the window has already been added, but during resume
4445 // we started another activity, then don't yet make the
4446 // window visible.
4447 } else if (!willBeVisible) {
4448 if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
4449 r.hideForNow = true;
4450 }
4451
4452 // Get rid of anything left hanging around.
4453 cleanUpPendingRemoveWindows(r, false /* force */);
4454
4455 // The window is now visible if it has been added, we are not
4456 // simply finishing, and we are not starting another activity.
4457 if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
4458 if (r.newConfig != null) {
4459 performConfigurationChangedForActivity(r, r.newConfig,
4460 false /* alwaysReportChange */);
4461 if (DEBUG_CONFIGURATION) {
4462 Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
4463 + r.activity.mCurrentConfig);
4464 }
4465 r.newConfig = null;
4466 }
4467 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
4468 ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
4469 WindowManager.LayoutParams l = impl != null
4470 ? impl.mWindowAttributes : r.window.getAttributes();
4471 if ((l.softInputMode
4472 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
4473 != forwardBit) {
4474 l.softInputMode = (l.softInputMode
4475 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
4476 | forwardBit;
4477 if (r.activity.mVisibleFromClient) {
4478 ViewManager wm = a.getWindowManager();
4479 View decor = r.window.getDecorView();
4480 wm.updateViewLayout(decor, l);
4481 }
4482 }
4483
4484 r.activity.mVisibleFromServer = true;
4485 mNumVisibleActivities++;
4486 if (r.activity.mVisibleFromClient) {
4487 r.activity.makeVisible();
4488 }
4489 }
4490
4491 r.nextIdle = mNewActivities;
4492 mNewActivities = r;
4493 if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
4494 Looper.myQueue().addIdleHandler(new Idler());
4495 }
4496
4497
4498 @Override
4499 public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) {
4500 ActivityClientRecord r = mActivities.get(token);
4501 if (r == null || r.activity == null) {
4502 Slog.w(TAG, "Not found target activity to report position change for token: " + token);
4503 return;
4504 }
4505
4506 if (DEBUG_ORDER) {
4507 Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r);
4508 }
4509
4510 if (r.isTopResumedActivity == onTop) {
4511 throw new IllegalStateException("Activity top position already set to onTop=" + onTop);
4512 }
4513
4514 r.isTopResumedActivity = onTop;
4515
4516 if (r.getLifecycleState() == ON_RESUME) {
4517 reportTopResumedActivityChanged(r, onTop, "topStateChangedWhenResumed");
4518 } else {
4519 if (DEBUG_ORDER) {
4520 Slog.d(TAG, "Won't deliver top position change in state=" + r.getLifecycleState());
4521 }
4522 }
4523 }
4524
4525 /**
4526 * Call {@link Activity#onTopResumedActivityChanged(boolean)} if its top resumed state changed
4527 * since the last report.
4528 */
4529 private void reportTopResumedActivityChanged(ActivityClientRecord r, boolean onTop,
4530 String reason) {
4531 if (r.lastReportedTopResumedState != onTop) {
4532 r.lastReportedTopResumedState = onTop;
4533 r.activity.performTopResumedActivityChanged(onTop, reason);
4534 }
4535 }
4536
4537 @Override
4538 public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
4539 int configChanges, PendingTransactionActions pendingActions, String reason) {
4540 ActivityClientRecord r = mActivities.get(token);
4541 if (r != null) {
4542 if (userLeaving) {
4543 performUserLeavingActivity(r);
4544 }
4545
4546 r.activity.mConfigChangeFlags |= configChanges;
4547 performPauseActivity(r, finished, reason, pendingActions);
4548
4549 // Make sure any pending writes are now committed.
4550 if (r.isPreHoneycomb()) {
4551 QueuedWork.waitToFinish();
4552 }
4553 mSomeActivitiesChanged = true;
4554 }
4555 }
4556
4557 final void performUserLeavingActivity(ActivityClientRecord r) {
4558 mInstrumentation.callActivityOnPictureInPictureRequested(r.activity);
4559 mInstrumentation.callActivityOnUserLeaving(r.activity);
4560 }
4561
4562 final Bundle performPauseActivity(IBinder token, boolean finished, String reason,
4563 PendingTransactionActions pendingActions) {
4564 ActivityClientRecord r = mActivities.get(token);
4565 return r != null ? performPauseActivity(r, finished, reason, pendingActions) : null;
4566 }
4567
4568 /**
4569 * Pause the activity.
4570 * @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
4571 */
4572 private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
4573 PendingTransactionActions pendingActions) {
4574 if (r.paused) {
4575 if (r.activity.mFinished) {
4576 // If we are finishing, we won't call onResume() in certain cases.
4577 // So here we likewise don't want to call onPause() if the activity
4578 // isn't resumed.
4579 return null;
4580 }
4581 RuntimeException e = new RuntimeException(
4582 "Performing pause of activity that is not resumed: "
4583 + r.intent.getComponent().toShortString());
4584 Slog.e(TAG, e.getMessage(), e);
4585 }
4586 if (finished) {
4587 r.activity.mFinished = true;
4588 }
4589
4590 // Pre-Honeycomb apps always save their state before pausing
4591 final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
4592 if (shouldSaveState) {
4593 callActivityOnSaveInstanceState(r);
4594 }
4595
4596 performPauseActivityIfNeeded(r, reason);
4597
4598 // Notify any outstanding on paused listeners
4599 ArrayList<OnActivityPausedListener> listeners;
4600 synchronized (mOnPauseListeners) {
4601 listeners = mOnPauseListeners.remove(r.activity);
4602 }
4603 int size = (listeners != null ? listeners.size() : 0);
4604 for (int i = 0; i < size; i++) {
4605 listeners.get(i).onPaused(r.activity);
4606 }
4607
4608 final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
4609 if (oldState != null) {
4610 // We need to keep around the original state, in case we need to be created again.
4611 // But we only do this for pre-Honeycomb apps, which always save their state when
4612 // pausing, so we can not have them save their state when restarting from a paused
4613 // state. For HC and later, we want to (and can) let the state be saved as the
4614 // normal part of stopping the activity.
4615 if (r.isPreHoneycomb()) {
4616 r.state = oldState;
4617 }
4618 }
4619
4620 return shouldSaveState ? r.state : null;
4621 }
4622
4623 private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
4624 if (r.paused) {
4625 // You are already paused silly...
4626 return;
4627 }
4628
4629 // Always reporting top resumed position loss when pausing an activity. If necessary, it
4630 // will be restored in performResumeActivity().
4631 reportTopResumedActivityChanged(r, false /* onTop */, "pausing");
4632
4633 try {
4634 r.activity.mCalled = false;
4635 mInstrumentation.callActivityOnPause(r.activity);
4636 if (!r.activity.mCalled) {
4637 throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
4638 + " did not call through to super.onPause()");
4639 }
4640 } catch (SuperNotCalledException e) {
4641 throw e;
4642 } catch (Exception e) {
4643 if (!mInstrumentation.onException(r.activity, e)) {
4644 throw new RuntimeException("Unable to pause activity "
4645 + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
4646 }
4647 }
4648 r.setState(ON_PAUSE);
4649 }
4650
4651 /** Called from {@link LocalActivityManager}. */
4652 @UnsupportedAppUsage
4653 final void performStopActivity(IBinder token, boolean saveState, String reason) {
4654 ActivityClientRecord r = mActivities.get(token);
4655 performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,
4656 reason);
4657 }
4658
4659 private static final class ProviderRefCount {
4660 public final ContentProviderHolder holder;
4661 public final ProviderClientRecord client;
4662 public int stableCount;
4663 public int unstableCount;
4664
4665 // When this is set, the stable and unstable ref counts are 0 and
4666 // we have a pending operation scheduled to remove the ref count
4667 // from the activity manager. On the activity manager we are still
4668 // holding an unstable ref, though it is not reflected in the counts
4669 // here.
4670 public boolean removePending;
4671
4672 ProviderRefCount(ContentProviderHolder inHolder,
4673 ProviderClientRecord inClient, int sCount, int uCount) {
4674 holder = inHolder;
4675 client = inClient;
4676 stableCount = sCount;
4677 unstableCount = uCount;
4678 }
4679 }
4680
4681 /**
4682 * Core implementation of stopping an activity.
4683 * @param r Target activity client record.
4684 * @param info Action that will report activity stop to server.
4685 * @param saveState Flag indicating whether the activity state should be saved.
4686 * @param finalStateRequest Flag indicating if this call is handling final lifecycle state
4687 * request for a transaction.
4688 * @param reason Reason for performing this operation.
4689 */
4690 private void performStopActivityInner(ActivityClientRecord r, StopInfo info,
4691 boolean saveState, boolean finalStateRequest, String reason) {
4692 if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
4693 if (r != null) {
4694 if (r.stopped) {
4695 if (r.activity.mFinished) {
4696 // If we are finishing, we won't call onResume() in certain
4697 // cases. So here we likewise don't want to call onStop()
4698 // if the activity isn't resumed.
4699 return;
4700 }
4701 if (!finalStateRequest) {
4702 final RuntimeException e = new RuntimeException(
4703 "Performing stop of activity that is already stopped: "
4704 + r.intent.getComponent().toShortString());
4705 Slog.e(TAG, e.getMessage(), e);
4706 Slog.e(TAG, r.getStateString());
4707 }
4708 }
4709
4710 // One must first be paused before stopped...
4711 performPauseActivityIfNeeded(r, reason);
4712
4713 if (info != null) {
4714 try {
4715 // First create a thumbnail for the activity...
4716 // For now, don't create the thumbnail here; we are
4717 // doing that by doing a screen snapshot.
4718 info.setDescription(r.activity.onCreateDescription());
4719 } catch (Exception e) {
4720 if (!mInstrumentation.onException(r.activity, e)) {
4721 throw new RuntimeException(
4722 "Unable to save state of activity "
4723 + r.intent.getComponent().toShortString()
4724 + ": " + e.toString(), e);
4725 }
4726 }
4727 }
4728
4729 callActivityOnStop(r, saveState, reason);
4730 }
4731 }
4732
4733 /**
4734 * Calls {@link Activity#onStop()} and {@link Activity#onSaveInstanceState(Bundle)}, and updates
4735 * the client record's state.
4736 * All calls to stop an activity must be done through this method to make sure that
4737 * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call.
4738 */
4739 private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
4740 // Before P onSaveInstanceState was called before onStop, starting with P it's
4741 // called after. Before Honeycomb state was always saved before onPause.
4742 final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
4743 && !r.isPreHoneycomb();
4744 final boolean isPreP = r.isPreP();
4745 if (shouldSaveState && isPreP) {
4746 callActivityOnSaveInstanceState(r);
4747 }
4748
4749 try {
4750 r.activity.performStop(r.mPreserveWindow, reason);
4751 } catch (SuperNotCalledException e) {
4752 throw e;
4753 } catch (Exception e) {
4754 if (!mInstrumentation.onException(r.activity, e)) {
4755 throw new RuntimeException(
4756 "Unable to stop activity "
4757 + r.intent.getComponent().toShortString()
4758 + ": " + e.toString(), e);
4759 }
4760 }
4761 r.setState(ON_STOP);
4762
4763 if (shouldSaveState && !isPreP) {
4764 callActivityOnSaveInstanceState(r);
4765 }
4766 }
4767
4768 private void updateVisibility(ActivityClientRecord r, boolean show) {
4769 View v = r.activity.mDecor;
4770 if (v != null) {
4771 if (show) {
4772 if (!r.activity.mVisibleFromServer) {
4773 r.activity.mVisibleFromServer = true;
4774 mNumVisibleActivities++;
4775 if (r.activity.mVisibleFromClient) {
4776 r.activity.makeVisible();
4777 }
4778 }
4779 if (r.newConfig != null) {
4780 performConfigurationChangedForActivity(r, r.newConfig,
4781 false /* alwaysReportChange */);
4782 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
4783 + r.activityInfo.name + " with new config "
4784 + r.activity.mCurrentConfig);
4785 r.newConfig = null;
4786 }
4787 } else {
4788 if (r.activity.mVisibleFromServer) {
4789 r.activity.mVisibleFromServer = false;
4790 mNumVisibleActivities--;
4791 v.setVisibility(View.INVISIBLE);
4792 }
4793 }
4794 }
4795 }
4796
4797 @Override
4798 public void handleStopActivity(IBinder token, int configChanges,
4799 PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
4800 final ActivityClientRecord r = mActivities.get(token);
4801 r.activity.mConfigChangeFlags |= configChanges;
4802
4803 final StopInfo stopInfo = new StopInfo();
4804 performStopActivityInner(r, stopInfo, true /* saveState */, finalStateRequest,
4805 reason);
4806
4807 if (localLOGV) Slog.v(
4808 TAG, "Finishing stop of " + r + ": win=" + r.window);
4809
4810 updateVisibility(r, false);
4811
4812 // Make sure any pending writes are now committed.
4813 if (!r.isPreHoneycomb()) {
4814 QueuedWork.waitToFinish();
4815 }
4816
4817 stopInfo.setActivity(r);
4818 stopInfo.setState(r.state);
4819 stopInfo.setPersistentState(r.persistentState);
4820 pendingActions.setStopInfo(stopInfo);
4821 mSomeActivitiesChanged = true;
4822 }
4823
4824 /**
4825 * Schedule the call to tell the activity manager we have stopped. We don't do this
4826 * immediately, because we want to have a chance for any other pending work (in particular
4827 * memory trim requests) to complete before you tell the activity manager to proceed and allow
4828 * us to go fully into the background.
4829 */
4830 @Override
4831 public void reportStop(PendingTransactionActions pendingActions) {
4832 mH.post(pendingActions.getStopInfo());
4833 }
4834
4835 @Override
4836 public void performRestartActivity(IBinder token, boolean start) {
4837 ActivityClientRecord r = mActivities.get(token);
4838 if (r.stopped) {
4839 r.activity.performRestart(start, "performRestartActivity");
4840 if (start) {
4841 r.setState(ON_START);
4842 }
4843 }
4844 }
4845
4846 private void handleSetCoreSettings(Bundle coreSettings) {
4847 synchronized (mResourcesManager) {
4848 mCoreSettings = coreSettings;
4849 }
4850 onCoreSettingsChange();
4851 }
4852
4853 private void onCoreSettingsChange() {
4854 if (updateDebugViewAttributeState()) {
4855 // request all activities to relaunch for the changes to take place
4856 relaunchAllActivities(false /* preserveWindows */);
4857 }
4858 }
4859
4860 private boolean updateDebugViewAttributeState() {
4861 boolean previousState = View.sDebugViewAttributes;
4862
4863 View.sDebugViewAttributesApplicationPackage = mCoreSettings.getString(
4864 Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, "");
4865 String currentPackage = (mBoundApplication != null && mBoundApplication.appInfo != null)
4866 ? mBoundApplication.appInfo.packageName : "<unknown-app>";
4867 View.sDebugViewAttributes =
4868 mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0
4869 || View.sDebugViewAttributesApplicationPackage.equals(currentPackage);
4870 return previousState != View.sDebugViewAttributes;
4871 }
4872
4873 private void relaunchAllActivities(boolean preserveWindows) {
4874 for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
4875 final ActivityClientRecord r = entry.getValue();
4876 if (!r.activity.mFinished) {
4877 if (preserveWindows && r.window != null) {
4878 r.mPreserveWindow = true;
4879 }
4880 scheduleRelaunchActivity(entry.getKey());
4881 }
4882 }
4883 }
4884
4885 private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
4886 LoadedApk apk = peekPackageInfo(data.pkg, false);
4887 if (apk != null) {
4888 apk.setCompatibilityInfo(data.info);
4889 }
4890 apk = peekPackageInfo(data.pkg, true);
4891 if (apk != null) {
4892 apk.setCompatibilityInfo(data.info);
4893 }
4894 handleConfigurationChanged(mConfiguration, data.info);
4895 WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
4896 }
4897
4898 private void deliverResults(ActivityClientRecord r, List<ResultInfo> results, String reason) {
4899 final int N = results.size();
4900 for (int i=0; i<N; i++) {
4901 ResultInfo ri = results.get(i);
4902 try {
4903 if (ri.mData != null) {
4904 ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
4905 ri.mData.prepareToEnterProcess();
4906 }
4907 if (DEBUG_RESULTS) Slog.v(TAG,
4908 "Delivering result to activity " + r + " : " + ri);
4909 r.activity.dispatchActivityResult(ri.mResultWho,
4910 ri.mRequestCode, ri.mResultCode, ri.mData, reason);
4911 } catch (Exception e) {
4912 if (!mInstrumentation.onException(r.activity, e)) {
4913 throw new RuntimeException(
4914 "Failure delivering result " + ri + " to activity "
4915 + r.intent.getComponent().toShortString()
4916 + ": " + e.toString(), e);
4917 }
4918 }
4919 }
4920 }
4921
4922 @Override
4923 public void handleSendResult(IBinder token, List<ResultInfo> results, String reason) {
4924 ActivityClientRecord r = mActivities.get(token);
4925 if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
4926 if (r != null) {
4927 final boolean resumed = !r.paused;
4928 if (!r.activity.mFinished && r.activity.mDecor != null
4929 && r.hideForNow && resumed) {
4930 // We had hidden the activity because it started another
4931 // one... we have gotten a result back and we are not
4932 // paused, so make sure our window is visible.
4933 updateVisibility(r, true);
4934 }
4935 if (resumed) {
4936 try {
4937 // Now we are idle.
4938 r.activity.mCalled = false;
4939 mInstrumentation.callActivityOnPause(r.activity);
4940 if (!r.activity.mCalled) {
4941 throw new SuperNotCalledException(
4942 "Activity " + r.intent.getComponent().toShortString()
4943 + " did not call through to super.onPause()");
4944 }
4945 } catch (SuperNotCalledException e) {
4946 throw e;
4947 } catch (Exception e) {
4948 if (!mInstrumentation.onException(r.activity, e)) {
4949 throw new RuntimeException(
4950 "Unable to pause activity "
4951 + r.intent.getComponent().toShortString()
4952 + ": " + e.toString(), e);
4953 }
4954 }
4955 }
4956 checkAndBlockForNetworkAccess();
4957 deliverResults(r, results, reason);
4958 if (resumed) {
4959 r.activity.performResume(false, reason);
4960 }
4961 }
4962 }
4963
4964 /** Core implementation of activity destroy call. */
4965 ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
4966 int configChanges, boolean getNonConfigInstance, String reason) {
4967 ActivityClientRecord r = mActivities.get(token);
4968 Class<? extends Activity> activityClass = null;
4969 if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
4970 if (r != null) {
4971 activityClass = r.activity.getClass();
4972 r.activity.mConfigChangeFlags |= configChanges;
4973 if (finishing) {
4974 r.activity.mFinished = true;
4975 }
4976
4977 performPauseActivityIfNeeded(r, "destroy");
4978
4979 if (!r.stopped) {
4980 callActivityOnStop(r, false /* saveState */, "destroy");
4981 }
4982 if (getNonConfigInstance) {
4983 try {
4984 r.lastNonConfigurationInstances
4985 = r.activity.retainNonConfigurationInstances();
4986 } catch (Exception e) {
4987 if (!mInstrumentation.onException(r.activity, e)) {
4988 throw new RuntimeException(
4989 "Unable to retain activity "
4990 + r.intent.getComponent().toShortString()
4991 + ": " + e.toString(), e);
4992 }
4993 }
4994 }
4995 try {
4996 r.activity.mCalled = false;
4997 mInstrumentation.callActivityOnDestroy(r.activity);
4998 if (!r.activity.mCalled) {
4999 throw new SuperNotCalledException(
5000 "Activity " + safeToComponentShortString(r.intent) +
5001 " did not call through to super.onDestroy()");
5002 }
5003 if (r.window != null) {
5004 r.window.closeAllPanels();
5005 }
5006 } catch (SuperNotCalledException e) {
5007 throw e;
5008 } catch (Exception e) {
5009 if (!mInstrumentation.onException(r.activity, e)) {
5010 throw new RuntimeException(
5011 "Unable to destroy activity " + safeToComponentShortString(r.intent)
5012 + ": " + e.toString(), e);
5013 }
5014 }
5015 r.setState(ON_DESTROY);
5016 }
5017 schedulePurgeIdler();
5018 // updatePendingActivityConfiguration() reads from mActivities to update
5019 // ActivityClientRecord which runs in a different thread. Protect modifications to
5020 // mActivities to avoid race.
5021 synchronized (mResourcesManager) {
5022 mActivities.remove(token);
5023 }
5024 StrictMode.decrementExpectedActivityCount(activityClass);
5025 return r;
5026 }
5027
5028 private static String safeToComponentShortString(Intent intent) {
5029 ComponentName component = intent.getComponent();
5030 return component == null ? "[Unknown]" : component.toShortString();
5031 }
5032
5033 @Override
5034 public Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed() {
5035 return mActivitiesToBeDestroyed;
5036 }
5037
5038 @Override
5039 public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
5040 boolean getNonConfigInstance, String reason) {
5041 ActivityClientRecord r = performDestroyActivity(token, finishing,
5042 configChanges, getNonConfigInstance, reason);
5043 if (r != null) {
5044 cleanUpPendingRemoveWindows(r, finishing);
5045 WindowManager wm = r.activity.getWindowManager();
5046 View v = r.activity.mDecor;
5047 if (v != null) {
5048 if (r.activity.mVisibleFromServer) {
5049 mNumVisibleActivities--;
5050 }
5051 IBinder wtoken = v.getWindowToken();
5052 if (r.activity.mWindowAdded) {
5053 if (r.mPreserveWindow) {
5054 // Hold off on removing this until the new activity's
5055 // window is being added.
5056 r.mPendingRemoveWindow = r.window;
5057 r.mPendingRemoveWindowManager = wm;
5058 // We can only keep the part of the view hierarchy that we control,
5059 // everything else must be removed, because it might not be able to
5060 // behave properly when activity is relaunching.
5061 r.window.clearContentView();
5062 } else {
5063 wm.removeViewImmediate(v);
5064 }
5065 }
5066 if (wtoken != null && r.mPendingRemoveWindow == null) {
5067 WindowManagerGlobal.getInstance().closeAll(wtoken,
5068 r.activity.getClass().getName(), "Activity");
5069 } else if (r.mPendingRemoveWindow != null) {
5070 // We're preserving only one window, others should be closed so app views
5071 // will be detached before the final tear down. It should be done now because
5072 // some components (e.g. WebView) rely on detach callbacks to perform receiver
5073 // unregister and other cleanup.
5074 WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
5075 r.activity.getClass().getName(), "Activity");
5076 }
5077 r.activity.mDecor = null;
5078 }
5079 if (r.mPendingRemoveWindow == null) {
5080 // If we are delaying the removal of the activity window, then
5081 // we can't clean up all windows here. Note that we can't do
5082 // so later either, which means any windows that aren't closed
5083 // by the app will leak. Well we try to warning them a lot
5084 // about leaking windows, because that is a bug, so if they are
5085 // using this recreate facility then they get to live with leaks.
5086 WindowManagerGlobal.getInstance().closeAll(token,
5087 r.activity.getClass().getName(), "Activity");
5088 }
5089
5090 // Mocked out contexts won't be participating in the normal
5091 // process lifecycle, but if we're running with a proper
5092 // ApplicationContext we need to have it tear down things
5093 // cleanly.
5094 Context c = r.activity.getBaseContext();
5095 if (c instanceof ContextImpl) {
5096 ((ContextImpl) c).scheduleFinalCleanup(
5097 r.activity.getClass().getName(), "Activity");
5098 }
5099 }
5100 if (finishing) {
5101 try {
5102 ActivityTaskManager.getService().activityDestroyed(token);
5103 } catch (RemoteException ex) {
5104 throw ex.rethrowFromSystemServer();
5105 }
5106 }
5107 mSomeActivitiesChanged = true;
5108 }
5109
5110 @Override
5111 public ActivityClientRecord prepareRelaunchActivity(IBinder token,
5112 List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
5113 int configChanges, MergedConfiguration config, boolean preserveWindow) {
5114 ActivityClientRecord target = null;
5115 boolean scheduleRelaunch = false;
5116
5117 synchronized (mResourcesManager) {
5118 for (int i=0; i<mRelaunchingActivities.size(); i++) {
5119 ActivityClientRecord r = mRelaunchingActivities.get(i);
5120 if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + this + ", trying: " + r);
5121 if (r.token == token) {
5122 target = r;
5123 if (pendingResults != null) {
5124 if (r.pendingResults != null) {
5125 r.pendingResults.addAll(pendingResults);
5126 } else {
5127 r.pendingResults = pendingResults;
5128 }
5129 }
5130 if (pendingNewIntents != null) {
5131 if (r.pendingIntents != null) {
5132 r.pendingIntents.addAll(pendingNewIntents);
5133 } else {
5134 r.pendingIntents = pendingNewIntents;
5135 }
5136 }
5137 break;
5138 }
5139 }
5140
5141 if (target == null) {
5142 if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null");
5143 target = new ActivityClientRecord();
5144 target.token = token;
5145 target.pendingResults = pendingResults;
5146 target.pendingIntents = pendingNewIntents;
5147 target.mPreserveWindow = preserveWindow;
5148 mRelaunchingActivities.add(target);
5149 scheduleRelaunch = true;
5150 }
5151 target.createdConfig = config.getGlobalConfiguration();
5152 target.overrideConfig = config.getOverrideConfiguration();
5153 target.pendingConfigChanges |= configChanges;
5154 }
5155
5156 return scheduleRelaunch ? target : null;
5157 }
5158
5159 @Override
5160 public void handleRelaunchActivity(ActivityClientRecord tmp,
5161 PendingTransactionActions pendingActions) {
5162 // If we are getting ready to gc after going to the background, well
5163 // we are back active so skip it.
5164 unscheduleGcIdler();
5165 mSomeActivitiesChanged = true;
5166
5167 Configuration changedConfig = null;
5168 int configChanges = 0;
5169
5170 // First: make sure we have the most recent configuration and most
5171 // recent version of the activity, or skip it if some previous call
5172 // had taken a more recent version.
5173 synchronized (mResourcesManager) {
5174 int N = mRelaunchingActivities.size();
5175 IBinder token = tmp.token;
5176 tmp = null;
5177 for (int i=0; i<N; i++) {
5178 ActivityClientRecord r = mRelaunchingActivities.get(i);
5179 if (r.token == token) {
5180 tmp = r;
5181 configChanges |= tmp.pendingConfigChanges;
5182 mRelaunchingActivities.remove(i);
5183 i--;
5184 N--;
5185 }
5186 }
5187
5188 if (tmp == null) {
5189 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
5190 return;
5191 }
5192
5193 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
5194 + tmp.token + " with configChanges=0x"
5195 + Integer.toHexString(configChanges));
5196
5197 if (mPendingConfiguration != null) {
5198 changedConfig = mPendingConfiguration;
5199 mPendingConfiguration = null;
5200 }
5201 }
5202
5203 if (tmp.createdConfig != null) {
5204 // If the activity manager is passing us its current config,
5205 // assume that is really what we want regardless of what we
5206 // may have pending.
5207 if (mConfiguration == null
5208 || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
5209 && mConfiguration.diff(tmp.createdConfig) != 0)) {
5210 if (changedConfig == null
5211 || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
5212 changedConfig = tmp.createdConfig;
5213 }
5214 }
5215 }
5216
5217 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
5218 + tmp.token + ": changedConfig=" + changedConfig);
5219
5220 // If there was a pending configuration change, execute it first.
5221 if (changedConfig != null) {
5222 mCurDefaultDisplayDpi = changedConfig.densityDpi;
5223 updateDefaultDensity();
5224 handleConfigurationChanged(changedConfig, null);
5225 }
5226
5227 ActivityClientRecord r = mActivities.get(tmp.token);
5228 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
5229 if (r == null) {
5230 return;
5231 }
5232
5233 r.activity.mConfigChangeFlags |= configChanges;
5234 r.mPreserveWindow = tmp.mPreserveWindow;
5235
5236 r.activity.mChangingConfigurations = true;
5237
5238 // If we are preserving the main window across relaunches we would also like to preserve
5239 // the children. However the client side view system does not support preserving
5240 // the child views so we notify the window manager to expect these windows to
5241 // be replaced and defer requests to destroy or hide them. This way we can achieve
5242 // visual continuity. It's important that we do this here prior to pause and destroy
5243 // as that is when we may hide or remove the child views.
5244 //
5245 // There is another scenario, if we have decided locally to relaunch the app from a
5246 // call to recreate, then none of the windows will be prepared for replacement or
5247 // preserved by the server, so we want to notify it that we are preparing to replace
5248 // everything
5249 try {
5250 if (r.mPreserveWindow) {
5251 WindowManagerGlobal.getWindowSession().prepareToReplaceWindows(
5252 r.token, true /* childrenOnly */);
5253 }
5254 } catch (RemoteException e) {
5255 throw e.rethrowFromSystemServer();
5256 }
5257
5258 // Save the current windowing mode to be restored and compared to the new configuration's
5259 // windowing mode (needed because we update the last reported windowing mode when launching
5260 // an activity and we can't tell inside performLaunchActivity whether we are relaunching)
5261 final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(
5262 r.activity.getActivityToken(), WINDOWING_MODE_UNDEFINED);
5263 handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
5264 pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
5265 mLastReportedWindowingMode.put(r.activity.getActivityToken(), oldWindowingMode);
5266 handleWindowingModeChangeIfNeeded(r.activity, r.activity.mCurrentConfig);
5267
5268 if (pendingActions != null) {
5269 // Only report a successful relaunch to WindowManager.
5270 pendingActions.setReportRelaunchToWindowManager(true);
5271 }
5272 }
5273
5274 /**
5275 * Post a message to relaunch the activity. We do this instead of launching it immediately,
5276 * because this will destroy the activity from which it was called and interfere with the
5277 * lifecycle changes it was going through before. We need to make sure that we have finished
5278 * handling current transaction item before relaunching the activity.
5279 */
5280 void scheduleRelaunchActivity(IBinder token) {
5281 mH.removeMessages(H.RELAUNCH_ACTIVITY, token);
5282 sendMessage(H.RELAUNCH_ACTIVITY, token);
5283 }
5284
5285 /** Performs the activity relaunch locally vs. requesting from system-server. */
5286 private void handleRelaunchActivityLocally(IBinder token) {
5287 final ActivityClientRecord r = mActivities.get(token);
5288 if (r == null) {
5289 Log.w(TAG, "Activity to relaunch no longer exists");
5290 return;
5291 }
5292
5293 final int prevState = r.getLifecycleState();
5294
5295 if (prevState < ON_RESUME || prevState > ON_STOP) {
5296 Log.w(TAG, "Activity state must be in [ON_RESUME..ON_STOP] in order to be relaunched,"
5297 + "current state is " + prevState);
5298 return;
5299 }
5300
5301
5302 // Initialize a relaunch request.
5303 final MergedConfiguration mergedConfiguration = new MergedConfiguration(
5304 r.createdConfig != null ? r.createdConfig : mConfiguration,
5305 r.overrideConfig);
5306 final ActivityRelaunchItem activityRelaunchItem = ActivityRelaunchItem.obtain(
5307 null /* pendingResults */, null /* pendingIntents */, 0 /* configChanges */,
5308 mergedConfiguration, r.mPreserveWindow);
5309 // Make sure to match the existing lifecycle state in the end of the transaction.
5310 final ActivityLifecycleItem lifecycleRequest =
5311 TransactionExecutorHelper.getLifecycleRequestForCurrentState(r);
5312 // Schedule the transaction.
5313 final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
5314 transaction.addCallback(activityRelaunchItem);
5315 transaction.setLifecycleStateRequest(lifecycleRequest);
5316 executeTransaction(transaction);
5317 }
5318
5319 private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
5320 List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
5321 PendingTransactionActions pendingActions, boolean startsNotResumed,
5322 Configuration overrideConfig, String reason) {
5323 // Preserve last used intent, it may be set from Activity#setIntent().
5324 final Intent customIntent = r.activity.mIntent;
5325 // Need to ensure state is saved.
5326 if (!r.paused) {
5327 performPauseActivity(r, false, reason, null /* pendingActions */);
5328 }
5329 if (!r.stopped) {
5330 callActivityOnStop(r, true /* saveState */, reason);
5331 }
5332
5333 handleDestroyActivity(r.token, false, configChanges, true, reason);
5334
5335 r.activity = null;
5336 r.window = null;
5337 r.hideForNow = false;
5338 r.nextIdle = null;
5339 // Merge any pending results and pending intents; don't just replace them
5340 if (pendingResults != null) {
5341 if (r.pendingResults == null) {
5342 r.pendingResults = pendingResults;
5343 } else {
5344 r.pendingResults.addAll(pendingResults);
5345 }
5346 }
5347 if (pendingIntents != null) {
5348 if (r.pendingIntents == null) {
5349 r.pendingIntents = pendingIntents;
5350 } else {
5351 r.pendingIntents.addAll(pendingIntents);
5352 }
5353 }
5354 r.startsNotResumed = startsNotResumed;
5355 r.overrideConfig = overrideConfig;
5356
5357 handleLaunchActivity(r, pendingActions, customIntent);
5358 }
5359
5360 @Override
5361 public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) {
5362 try {
5363 ActivityTaskManager.getService().activityRelaunched(token);
5364 final ActivityClientRecord r = mActivities.get(token);
5365 if (pendingActions.shouldReportRelaunchToWindowManager() && r != null
5366 && r.window != null) {
5367 r.window.reportActivityRelaunched();
5368 }
5369 } catch (RemoteException e) {
5370 throw e.rethrowFromSystemServer();
5371 }
5372 }
5373
5374 private void callActivityOnSaveInstanceState(ActivityClientRecord r) {
5375 r.state = new Bundle();
5376 r.state.setAllowFds(false);
5377 if (r.isPersistable()) {
5378 r.persistentState = new PersistableBundle();
5379 mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
5380 r.persistentState);
5381 } else {
5382 mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
5383 }
5384 }
5385
5386 ArrayList<ComponentCallbacks2> collectComponentCallbacks(
5387 boolean allActivities, Configuration newConfig) {
5388 ArrayList<ComponentCallbacks2> callbacks
5389 = new ArrayList<ComponentCallbacks2>();
5390
5391 synchronized (mResourcesManager) {
5392 final int NAPP = mAllApplications.size();
5393 for (int i=0; i<NAPP; i++) {
5394 callbacks.add(mAllApplications.get(i));
5395 }
5396 final int NACT = mActivities.size();
5397 for (int i=0; i<NACT; i++) {
5398 ActivityClientRecord ar = mActivities.valueAt(i);
5399 Activity a = ar.activity;
5400 if (a != null) {
5401 Configuration thisConfig = applyConfigCompatMainThread(
5402 mCurDefaultDisplayDpi, newConfig,
5403 ar.packageInfo.getCompatibilityInfo());
5404 if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
5405 // If the activity is currently resumed, its configuration
5406 // needs to change right now.
5407 callbacks.add(a);
5408 } else if (thisConfig != null) {
5409 // Otherwise, we will tell it about the change
5410 // the next time it is resumed or shown. Note that
5411 // the activity manager may, before then, decide the
5412 // activity needs to be destroyed to handle its new
5413 // configuration.
5414 if (DEBUG_CONFIGURATION) {
5415 Slog.v(TAG, "Setting activity "
5416 + ar.activityInfo.name + " newConfig=" + thisConfig);
5417 }
5418 ar.newConfig = thisConfig;
5419 }
5420 }
5421 }
5422 final int NSVC = mServices.size();
5423 for (int i=0; i<NSVC; i++) {
5424 final ComponentCallbacks2 serviceComp = mServices.valueAt(i);
5425 if (serviceComp instanceof InputMethodService) {
5426 mHasImeComponent = true;
5427 }
5428 callbacks.add(serviceComp);
5429 }
5430 }
5431 synchronized (mProviderMap) {
5432 final int NPRV = mLocalProviders.size();
5433 for (int i=0; i<NPRV; i++) {
5434 callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
5435 }
5436 }
5437
5438 return callbacks;
5439 }
5440
5441 /**
5442 * Updates the configuration for an Activity. The ActivityClientRecord's
5443 * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
5444 * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
5445 * the updated Configuration.
5446 * @param r ActivityClientRecord representing the Activity.
5447 * @param newBaseConfig The new configuration to use. This may be augmented with
5448 * {@link ActivityClientRecord#overrideConfig}.
5449 * @param alwaysReportChange If the configuration is changed, always report to activity.
5450 */
5451 private void performConfigurationChangedForActivity(ActivityClientRecord r,
5452 Configuration newBaseConfig, boolean alwaysReportChange) {
5453 performConfigurationChangedForActivity(r, newBaseConfig, r.activity.getDisplayId(),
5454 false /* movedToDifferentDisplay */, alwaysReportChange);
5455 }
5456
5457 /**
5458 * Updates the configuration for an Activity. The ActivityClientRecord's
5459 * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
5460 * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
5461 * the updated Configuration.
5462 * @param r ActivityClientRecord representing the Activity.
5463 * @param newBaseConfig The new configuration to use. This may be augmented with
5464 * {@link ActivityClientRecord#overrideConfig}.
5465 * @param displayId The id of the display where the Activity currently resides.
5466 * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
5467 * @param alwaysReportChange If the configuration is changed, always report to activity.
5468 * @return {@link Configuration} instance sent to client, null if not sent.
5469 */
5470 private Configuration performConfigurationChangedForActivity(ActivityClientRecord r,
5471 Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay,
5472 boolean alwaysReportChange) {
5473 r.tmpConfig.setTo(newBaseConfig);
5474 if (r.overrideConfig != null) {
5475 r.tmpConfig.updateFrom(r.overrideConfig);
5476 }
5477 final Configuration reportedConfig = performActivityConfigurationChanged(r.activity,
5478 r.tmpConfig, r.overrideConfig, displayId, movedToDifferentDisplay,
5479 alwaysReportChange);
5480 freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
5481 return reportedConfig;
5482 }
5483
5484 /**
5485 * Creates a new Configuration only if override would modify base. Otherwise returns base.
5486 * @param base The base configuration.
5487 * @param override The update to apply to the base configuration. Can be null.
5488 * @return A Configuration representing base with override applied.
5489 */
5490 private static Configuration createNewConfigAndUpdateIfNotNull(@NonNull Configuration base,
5491 @Nullable Configuration override) {
5492 if (override == null) {
5493 return base;
5494 }
5495 Configuration newConfig = new Configuration(base);
5496 newConfig.updateFrom(override);
5497 return newConfig;
5498 }
5499
5500 /**
5501 * Decides whether to update a component's configuration and whether to inform it.
5502 * @param cb The component callback to notify of configuration change.
5503 * @param newConfig The new configuration.
5504 */
5505 private void performConfigurationChanged(ComponentCallbacks2 cb, Configuration newConfig) {
5506 if (!REPORT_TO_ACTIVITY) {
5507 return;
5508 }
5509
5510 // ContextThemeWrappers may override the configuration for that context. We must check and
5511 // apply any overrides defined.
5512 Configuration contextThemeWrapperOverrideConfig = null;
5513 if (cb instanceof ContextThemeWrapper) {
5514 final ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
5515 contextThemeWrapperOverrideConfig = contextThemeWrapper.getOverrideConfiguration();
5516 }
5517
5518 // Apply the ContextThemeWrapper override if necessary.
5519 // NOTE: Make sure the configurations are not modified, as they are treated as immutable
5520 // in many places.
5521 final Configuration configToReport = createNewConfigAndUpdateIfNotNull(
5522 newConfig, contextThemeWrapperOverrideConfig);
5523 cb.onConfigurationChanged(configToReport);
5524 }
5525
5526 /**
5527 * Decides whether to update an Activity's configuration and whether to inform it.
5528 * @param activity The activity to notify of configuration change.
5529 * @param newConfig The new configuration.
5530 * @param amOverrideConfig The override config that differentiates the Activity's configuration
5531 * from the base global configuration. This is supplied by
5532 * ActivityManager.
5533 * @param displayId Id of the display where activity currently resides.
5534 * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
5535 * @param alwaysReportChange If the configuration is changed, always report to activity.
5536 * @return Configuration sent to client, null if no changes and not moved to different display.
5537 */
5538 private Configuration performActivityConfigurationChanged(Activity activity,
5539 Configuration newConfig, Configuration amOverrideConfig, int displayId,
5540 boolean movedToDifferentDisplay, boolean alwaysReportChange) {
5541 if (activity == null) {
5542 throw new IllegalArgumentException("No activity provided.");
5543 }
5544 final IBinder activityToken = activity.getActivityToken();
5545 if (activityToken == null) {
5546 throw new IllegalArgumentException("Activity token not set. Is the activity attached?");
5547 }
5548
5549 // multi-window / pip mode changes, if any, should be sent before the configuration change
5550 // callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
5551 handleWindowingModeChangeIfNeeded(activity, newConfig);
5552
5553 boolean shouldChangeConfig = false;
5554 if (activity.mCurrentConfig == null) {
5555 shouldChangeConfig = true;
5556 } else {
5557 // If the new config is the same as the config this Activity is already running with and
5558 // the override config also didn't change, then don't bother calling
5559 // onConfigurationChanged.
5560 final int diff = activity.mCurrentConfig.diffPublicOnly(newConfig);
5561
5562 if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken,
5563 amOverrideConfig)) {
5564 // Always send the task-level config changes. For system-level configuration, if
5565 // this activity doesn't handle any of the config changes, then don't bother
5566 // calling onConfigurationChanged as we're going to destroy it.
5567 if (alwaysReportChange
5568 || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
5569 || !REPORT_TO_ACTIVITY) {
5570 shouldChangeConfig = true;
5571 }
5572 }
5573 }
5574 if (!shouldChangeConfig && !movedToDifferentDisplay) {
5575 // Nothing significant, don't proceed with updating and reporting.
5576 return null;
5577 }
5578
5579 // Propagate the configuration change to ResourcesManager and Activity.
5580
5581 // ContextThemeWrappers may override the configuration for that context. We must check and
5582 // apply any overrides defined.
5583 Configuration contextThemeWrapperOverrideConfig = activity.getOverrideConfiguration();
5584
5585 // We only update an Activity's configuration if this is not a global configuration change.
5586 // This must also be done before the callback, or else we violate the contract that the new
5587 // resources are available in ComponentCallbacks2#onConfigurationChanged(Configuration).
5588 // Also apply the ContextThemeWrapper override if necessary.
5589 // NOTE: Make sure the configurations are not modified, as they are treated as immutable in
5590 // many places.
5591 final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull(
5592 amOverrideConfig, contextThemeWrapperOverrideConfig);
5593 mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig,
5594 displayId, movedToDifferentDisplay);
5595
5596 activity.mConfigChangeFlags = 0;
5597 activity.mCurrentConfig = new Configuration(newConfig);
5598
5599 // Apply the ContextThemeWrapper override if necessary.
5600 // NOTE: Make sure the configurations are not modified, as they are treated as immutable
5601 // in many places.
5602 final Configuration configToReport = createNewConfigAndUpdateIfNotNull(newConfig,
5603 contextThemeWrapperOverrideConfig);
5604
5605 if (!REPORT_TO_ACTIVITY) {
5606 // Not configured to report to activity.
5607 return configToReport;
5608 }
5609
5610 if (movedToDifferentDisplay) {
5611 activity.dispatchMovedToDisplay(displayId, configToReport);
5612 }
5613
5614 if (shouldChangeConfig) {
5615 activity.mCalled = false;
5616 activity.onConfigurationChanged(configToReport);
5617 if (!activity.mCalled) {
5618 throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
5619 " did not call through to super.onConfigurationChanged()");
5620 }
5621 }
5622
5623 return configToReport;
5624 }
5625
5626 public final void applyConfigurationToResources(Configuration config) {
5627 synchronized (mResourcesManager) {
5628 mResourcesManager.applyConfigurationToResourcesLocked(config, null);
5629 }
5630 }
5631
5632 final Configuration applyCompatConfiguration(int displayDensity) {
5633 Configuration config = mConfiguration;
5634 if (mCompatConfiguration == null) {
5635 mCompatConfiguration = new Configuration();
5636 }
5637 mCompatConfiguration.setTo(mConfiguration);
5638 if (mResourcesManager.applyCompatConfigurationLocked(displayDensity,
5639 mCompatConfiguration)) {
5640 config = mCompatConfiguration;
5641 }
5642 return config;
5643 }
5644
5645 @Override
5646 public void handleConfigurationChanged(Configuration config) {
5647 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
5648 mCurDefaultDisplayDpi = config.densityDpi;
5649 handleConfigurationChanged(config, null /* compat */);
5650 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5651 }
5652
5653 private void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
5654
5655 int configDiff;
5656 boolean equivalent;
5657
5658 final Theme systemTheme = getSystemContext().getTheme();
5659 final Theme systemUiTheme = getSystemUiContext().getTheme();
5660
5661 synchronized (mResourcesManager) {
5662 if (mPendingConfiguration != null) {
5663 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
5664 config = mPendingConfiguration;
5665 mCurDefaultDisplayDpi = config.densityDpi;
5666 updateDefaultDensity();
5667 }
5668 mPendingConfiguration = null;
5669 }
5670
5671 if (config == null) {
5672 // TODO (b/135719017): Temporary log for debugging IME service.
5673 if (Build.IS_DEBUGGABLE && mHasImeComponent) {
5674 Log.w(TAG, "handleConfigurationChanged for IME app but config is null");
5675 }
5676 return;
5677 }
5678
5679 // This flag tracks whether the new configuration is fundamentally equivalent to the
5680 // existing configuration. This is necessary to determine whether non-activity callbacks
5681 // should receive notice when the only changes are related to non-public fields.
5682 // We do not gate calling {@link #performActivityConfigurationChanged} based on this
5683 // flag as that method uses the same check on the activity config override as well.
5684 equivalent = mConfiguration != null && (0 == mConfiguration.diffPublicOnly(config));
5685
5686 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
5687 + config);
5688
5689 mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
5690 updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
5691 mResourcesManager.getConfiguration().getLocales());
5692
5693 if (mConfiguration == null) {
5694 mConfiguration = new Configuration();
5695 }
5696 if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
5697 // TODO (b/135719017): Temporary log for debugging IME service.
5698 if (Build.IS_DEBUGGABLE && mHasImeComponent) {
5699 Log.w(TAG, "handleConfigurationChanged for IME app but config seq is obsolete "
5700 + ", config=" + config
5701 + ", mConfiguration=" + mConfiguration);
5702 }
5703 return;
5704 }
5705
5706 configDiff = mConfiguration.updateFrom(config);
5707 config = applyCompatConfiguration(mCurDefaultDisplayDpi);
5708
5709 if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
5710 systemTheme.rebase();
5711 }
5712
5713 if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
5714 systemUiTheme.rebase();
5715 }
5716 }
5717
5718 ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
5719
5720 freeTextLayoutCachesIfNeeded(configDiff);
5721
5722 if (callbacks != null) {
5723 final int N = callbacks.size();
5724 for (int i=0; i<N; i++) {
5725 ComponentCallbacks2 cb = callbacks.get(i);
5726 if (cb instanceof Activity) {
5727 // If callback is an Activity - call corresponding method to consider override
5728 // config and avoid onConfigurationChanged if it hasn't changed.
5729 Activity a = (Activity) cb;
5730 performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
5731 config, false /* alwaysReportChange */);
5732 } else if (!equivalent) {
5733 performConfigurationChanged(cb, config);
5734 } else {
5735 // TODO (b/135719017): Temporary log for debugging IME service.
5736 if (Build.IS_DEBUGGABLE && cb instanceof InputMethodService) {
5737 Log.w(TAG, "performConfigurationChanged didn't callback to IME "
5738 + ", configDiff=" + configDiff
5739 + ", mConfiguration=" + mConfiguration);
5740 }
5741 }
5742 }
5743 }
5744 }
5745
5746 /**
5747 * Sends windowing mode change callbacks to {@link Activity} if applicable.
5748 *
5749 * See also {@link Activity#onMultiWindowModeChanged(boolean, Configuration)} and
5750 * {@link Activity#onPictureInPictureModeChanged(boolean, Configuration)}
5751 */
5752 private void handleWindowingModeChangeIfNeeded(Activity activity,
5753 Configuration newConfiguration) {
5754 final int newWindowingMode = newConfiguration.windowConfiguration.getWindowingMode();
5755 final IBinder token = activity.getActivityToken();
5756 final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(token,
5757 WINDOWING_MODE_UNDEFINED);
5758 if (oldWindowingMode == newWindowingMode) return;
5759 // PiP callback is sent before the MW one.
5760 if (newWindowingMode == WINDOWING_MODE_PINNED) {
5761 activity.dispatchPictureInPictureModeChanged(true, newConfiguration);
5762 } else if (oldWindowingMode == WINDOWING_MODE_PINNED) {
5763 activity.dispatchPictureInPictureModeChanged(false, newConfiguration);
5764 }
5765 final boolean wasInMultiWindowMode = WindowConfiguration.inMultiWindowMode(
5766 oldWindowingMode);
5767 final boolean nowInMultiWindowMode = WindowConfiguration.inMultiWindowMode(
5768 newWindowingMode);
5769 if (wasInMultiWindowMode != nowInMultiWindowMode) {
5770 activity.dispatchMultiWindowModeChanged(nowInMultiWindowMode, newConfiguration);
5771 }
5772 mLastReportedWindowingMode.put(token, newWindowingMode);
5773 }
5774
5775 /**
5776 * Updates the application info.
5777 *
5778 * This only works in the system process. Must be called on the main thread.
5779 */
5780 public void handleSystemApplicationInfoChanged(@NonNull ApplicationInfo ai) {
5781 Preconditions.checkState(mSystemThread, "Must only be called in the system process");
5782 handleApplicationInfoChanged(ai);
5783 }
5784
5785 @VisibleForTesting(visibility = PACKAGE)
5786 public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
5787 // Updates triggered by package installation go through a package update
5788 // receiver. Here we try to capture ApplicationInfo changes that are
5789 // caused by other sources, such as overlays. That means we want to be as conservative
5790 // about code changes as possible. Take the diff of the old ApplicationInfo and the new
5791 // to see if anything needs to change.
5792 LoadedApk apk;
5793 LoadedApk resApk;
5794 // Update all affected loaded packages with new package information
5795 synchronized (mResourcesManager) {
5796 WeakReference<LoadedApk> ref = mPackages.get(ai.packageName);
5797 apk = ref != null ? ref.get() : null;
5798 ref = mResourcePackages.get(ai.packageName);
5799 resApk = ref != null ? ref.get() : null;
5800 }
5801
5802 final String[] oldResDirs = new String[2];
5803
5804 if (apk != null) {
5805 oldResDirs[0] = apk.getResDir();
5806 final ArrayList<String> oldPaths = new ArrayList<>();
5807 LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths);
5808 apk.updateApplicationInfo(ai, oldPaths);
5809 }
5810 if (resApk != null) {
5811 oldResDirs[1] = resApk.getResDir();
5812 final ArrayList<String> oldPaths = new ArrayList<>();
5813 LoadedApk.makePaths(this, resApk.getApplicationInfo(), oldPaths);
5814 resApk.updateApplicationInfo(ai, oldPaths);
5815 }
5816
5817 synchronized (mResourcesManager) {
5818 // Update all affected Resources objects to use new ResourcesImpl
5819 mResourcesManager.applyNewResourceDirsLocked(ai, oldResDirs);
5820 }
5821
5822 ApplicationPackageManager.configurationChanged();
5823
5824 // Trigger a regular Configuration change event, only with a different assetsSeq number
5825 // so that we actually call through to all components.
5826 // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to
5827 // store configurations per-process.
5828 Configuration newConfig = new Configuration();
5829 newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
5830 handleConfigurationChanged(newConfig, null);
5831
5832 // Preserve windows to avoid black flickers when overlays change.
5833 relaunchAllActivities(true /* preserveWindows */);
5834 }
5835
5836 static void freeTextLayoutCachesIfNeeded(int configDiff) {
5837 if (configDiff != 0) {
5838 // Ask text layout engine to free its caches if there is a locale change
5839 boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
5840 if (hasLocaleConfigChange) {
5841 Canvas.freeTextLayoutCaches();
5842 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
5843 }
5844 }
5845 }
5846
5847 @Override
5848 public void updatePendingActivityConfiguration(IBinder activityToken,
5849 Configuration overrideConfig) {
5850 final ActivityClientRecord r;
5851 synchronized (mResourcesManager) {
5852 r = mActivities.get(activityToken);
5853 }
5854
5855 if (r == null) {
5856 if (DEBUG_CONFIGURATION) {
5857 Slog.w(TAG, "Not found target activity to update its pending config.");
5858 }
5859 return;
5860 }
5861
5862 synchronized (r) {
5863 r.mPendingOverrideConfig = overrideConfig;
5864 }
5865 }
5866
5867 @Override
5868 public void handleActivityConfigurationChanged(IBinder activityToken,
5869 Configuration overrideConfig, int displayId) {
5870 handleActivityConfigurationChanged(activityToken, overrideConfig, displayId,
5871 // This is the only place that uses alwaysReportChange=true. The entry point should
5872 // be from ActivityConfigurationChangeItem or MoveToDisplayItem, so the server side
5873 // has confirmed the activity should handle the configuration instead of relaunch.
5874 // If Activity#onConfigurationChanged is called unexpectedly, then we can know it is
5875 // something wrong from server side.
5876 true /* alwaysReportChange */);
5877 }
5878
5879 /**
5880 * Handle new activity configuration and/or move to a different display.
5881 * @param activityToken Target activity token.
5882 * @param overrideConfig Activity override config.
5883 * @param displayId Id of the display where activity was moved to, -1 if there was no move and
5884 * value didn't change.
5885 * @param alwaysReportChange If the configuration is changed, always report to activity.
5886 */
5887 void handleActivityConfigurationChanged(IBinder activityToken, Configuration overrideConfig,
5888 int displayId, boolean alwaysReportChange) {
5889 ActivityClientRecord r = mActivities.get(activityToken);
5890 // Check input params.
5891 if (r == null || r.activity == null) {
5892 if (DEBUG_CONFIGURATION) Slog.w(TAG, "Not found target activity to report to: " + r);
5893 return;
5894 }
5895 final boolean movedToDifferentDisplay = displayId != INVALID_DISPLAY
5896 && displayId != r.activity.getDisplayId();
5897
5898 synchronized (r) {
5899 if (r.mPendingOverrideConfig != null
5900 && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
5901 overrideConfig = r.mPendingOverrideConfig;
5902 }
5903 r.mPendingOverrideConfig = null;
5904 }
5905
5906 if (r.overrideConfig != null && !r.overrideConfig.isOtherSeqNewer(overrideConfig)
5907 && !movedToDifferentDisplay) {
5908 if (DEBUG_CONFIGURATION) {
5909 Slog.v(TAG, "Activity already handled newer configuration so drop this"
5910 + " transaction. overrideConfig=" + overrideConfig + " r.overrideConfig="
5911 + r.overrideConfig);
5912 }
5913 return;
5914 }
5915
5916 // Perform updates.
5917 r.overrideConfig = overrideConfig;
5918 final ViewRootImpl viewRoot = r.activity.mDecor != null
5919 ? r.activity.mDecor.getViewRootImpl() : null;
5920
5921 if (movedToDifferentDisplay) {
5922 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity moved to display, activity:"
5923 + r.activityInfo.name + ", displayId=" + displayId
5924 + ", config=" + overrideConfig);
5925
5926 final Configuration reportedConfig = performConfigurationChangedForActivity(r,
5927 mCompatConfiguration, displayId, true /* movedToDifferentDisplay */,
5928 alwaysReportChange);
5929 if (viewRoot != null) {
5930 viewRoot.onMovedToDisplay(displayId, reportedConfig);
5931 }
5932 } else {
5933 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
5934 + r.activityInfo.name + ", config=" + overrideConfig);
5935 performConfigurationChangedForActivity(r, mCompatConfiguration, alwaysReportChange);
5936 }
5937 // Notify the ViewRootImpl instance about configuration changes. It may have initiated this
5938 // update to make sure that resources are updated before updating itself.
5939 if (viewRoot != null) {
5940 viewRoot.updateConfiguration(displayId);
5941 }
5942 mSomeActivitiesChanged = true;
5943 }
5944
5945 final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
5946 if (start) {
5947 try {
5948 switch (profileType) {
5949 default:
5950 mProfiler.setProfiler(profilerInfo);
5951 mProfiler.startProfiling();
5952 break;
5953 }
5954 } catch (RuntimeException e) {
5955 Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile
5956 + " -- can the process access this path?");
5957 } finally {
5958 profilerInfo.closeFd();
5959 }
5960 } else {
5961 switch (profileType) {
5962 default:
5963 mProfiler.stopProfiling();
5964 break;
5965 }
5966 }
5967 }
5968
5969 /**
5970 * Public entrypoint to stop profiling. This is required to end profiling when the app crashes,
5971 * so that profiler data won't be lost.
5972 *
5973 * @hide
5974 */
5975 public void stopProfiling() {
5976 if (mProfiler != null) {
5977 mProfiler.stopProfiling();
5978 }
5979 }
5980
5981 static void handleDumpHeap(DumpHeapData dhd) {
5982 if (dhd.runGc) {
5983 System.gc();
5984 System.runFinalization();
5985 System.gc();
5986 }
5987 try (ParcelFileDescriptor fd = dhd.fd) {
5988 if (dhd.managed) {
5989 Debug.dumpHprofData(dhd.path, fd.getFileDescriptor());
5990 } else if (dhd.mallocInfo) {
5991 Debug.dumpNativeMallocInfo(fd.getFileDescriptor());
5992 } else {
5993 Debug.dumpNativeHeap(fd.getFileDescriptor());
5994 }
5995 } catch (IOException e) {
5996 if (dhd.managed) {
5997 Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
5998 + " -- can the process access this path?", e);
5999 } else {
6000 Slog.w(TAG, "Failed to dump heap", e);
6001 }
6002 } catch (RuntimeException e) {
6003 // This should no longer happening now that we're copying the file descriptor.
6004 Slog.wtf(TAG, "Heap dumper threw a runtime exception", e);
6005 }
6006 try {
6007 ActivityManager.getService().dumpHeapFinished(dhd.path);
6008 } catch (RemoteException e) {
6009 throw e.rethrowFromSystemServer();
6010 }
6011 if (dhd.finishCallback != null) {
6012 dhd.finishCallback.sendResult(null);
6013 }
6014 }
6015
6016 final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
6017 boolean hasPkgInfo = false;
6018 switch (cmd) {
6019 case ApplicationThreadConstants.PACKAGE_REMOVED:
6020 case ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL:
6021 {
6022 final boolean killApp = cmd == ApplicationThreadConstants.PACKAGE_REMOVED;
6023 if (packages == null) {
6024 break;
6025 }
6026 synchronized (mResourcesManager) {
6027 for (int i = packages.length - 1; i >= 0; i--) {
6028 if (!hasPkgInfo) {
6029 WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
6030 if (ref != null && ref.get() != null) {
6031 hasPkgInfo = true;
6032 } else {
6033 ref = mResourcePackages.get(packages[i]);
6034 if (ref != null && ref.get() != null) {
6035 hasPkgInfo = true;
6036 }
6037 }
6038 }
6039 if (killApp) {
6040 mPackages.remove(packages[i]);
6041 mResourcePackages.remove(packages[i]);
6042 }
6043 }
6044 }
6045 break;
6046 }
6047 case ApplicationThreadConstants.PACKAGE_REPLACED:
6048 {
6049 if (packages == null) {
6050 break;
6051 }
6052
6053 List<String> packagesHandled = new ArrayList<>();
6054
6055 synchronized (mResourcesManager) {
6056 for (int i = packages.length - 1; i >= 0; i--) {
6057 String packageName = packages[i];
6058 WeakReference<LoadedApk> ref = mPackages.get(packageName);
6059 LoadedApk pkgInfo = ref != null ? ref.get() : null;
6060 if (pkgInfo != null) {
6061 hasPkgInfo = true;
6062 } else {
6063 ref = mResourcePackages.get(packageName);
6064 pkgInfo = ref != null ? ref.get() : null;
6065 if (pkgInfo != null) {
6066 hasPkgInfo = true;
6067 }
6068 }
6069 // If the package is being replaced, yet it still has a valid
6070 // LoadedApk object, the package was updated with _DONT_KILL.
6071 // Adjust it's internal references to the application info and
6072 // resources.
6073 if (pkgInfo != null) {
6074 packagesHandled.add(packageName);
6075 try {
6076 final ApplicationInfo aInfo =
6077 sPackageManager.getApplicationInfo(
6078 packageName,
6079 PackageManager.GET_SHARED_LIBRARY_FILES,
6080 UserHandle.myUserId());
6081
6082 if (mActivities.size() > 0) {
6083 for (ActivityClientRecord ar : mActivities.values()) {
6084 if (ar.activityInfo.applicationInfo.packageName
6085 .equals(packageName)) {
6086 ar.activityInfo.applicationInfo = aInfo;
6087 ar.packageInfo = pkgInfo;
6088 }
6089 }
6090 }
6091
6092 final String[] oldResDirs = { pkgInfo.getResDir() };
6093
6094 final ArrayList<String> oldPaths = new ArrayList<>();
6095 LoadedApk.makePaths(this, pkgInfo.getApplicationInfo(), oldPaths);
6096 pkgInfo.updateApplicationInfo(aInfo, oldPaths);
6097
6098 synchronized (mResourcesManager) {
6099 // Update affected Resources objects to use new ResourcesImpl
6100 mResourcesManager.applyNewResourceDirsLocked(aInfo, oldResDirs);
6101 }
6102 } catch (RemoteException e) {
6103 }
6104 }
6105 }
6106 }
6107
6108 try {
6109 getPackageManager().notifyPackagesReplacedReceived(
6110 packagesHandled.toArray(new String[0]));
6111 } catch (RemoteException ignored) {
6112 }
6113
6114 break;
6115 }
6116 }
6117 ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
6118 }
6119
6120 final void handleLowMemory() {
6121 ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
6122
6123 final int N = callbacks.size();
6124 for (int i=0; i<N; i++) {
6125 callbacks.get(i).onLowMemory();
6126 }
6127
6128 // Ask SQLite to free up as much memory as it can, mostly from its page caches.
6129 if (Process.myUid() != Process.SYSTEM_UID) {
6130 int sqliteReleased = SQLiteDatabase.releaseMemory();
6131 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
6132 }
6133
6134 // Ask graphics to free up as much as possible (font/image caches)
6135 Canvas.freeCaches();
6136
6137 // Ask text layout engine to free also as much as possible
6138 Canvas.freeTextLayoutCaches();
6139
6140 BinderInternal.forceGc("mem");
6141 }
6142
6143 private void handleTrimMemory(int level) {
6144 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
6145 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
6146
6147 ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
6148
6149 final int N = callbacks.size();
6150 for (int i = 0; i < N; i++) {
6151 callbacks.get(i).onTrimMemory(level);
6152 }
6153
6154 WindowManagerGlobal.getInstance().trimMemory(level);
6155 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6156
6157 if (SystemProperties.getInt("debug.am.run_gc_trim_level", Integer.MAX_VALUE) <= level) {
6158 unscheduleGcIdler();
6159 doGcIfNeeded("tm");
6160 }
6161 if (SystemProperties.getInt("debug.am.run_mallopt_trim_level", Integer.MAX_VALUE)
6162 <= level) {
6163 unschedulePurgeIdler();
6164 purgePendingResources();
6165 }
6166 }
6167
6168 private void setupGraphicsSupport(Context context) {
6169 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setupGraphicsSupport");
6170
6171 // The system package doesn't have real data directories, so don't set up cache paths.
6172 if (!"android".equals(context.getPackageName())) {
6173 // This cache location probably points at credential-encrypted
6174 // storage which may not be accessible yet; assign it anyway instead
6175 // of pointing at device-encrypted storage.
6176 final File cacheDir = context.getCacheDir();
6177 if (cacheDir != null) {
6178 // Provide a usable directory for temporary files
6179 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
6180 } else {
6181 Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
6182 + "due to missing cache directory");
6183 }
6184
6185 // Setup a location to store generated/compiled graphics code.
6186 final Context deviceContext = context.createDeviceProtectedStorageContext();
6187 final File codeCacheDir = deviceContext.getCodeCacheDir();
6188 if (codeCacheDir != null) {
6189 try {
6190 int uid = Process.myUid();
6191 String[] packages = getPackageManager().getPackagesForUid(uid);
6192 if (packages != null) {
6193 HardwareRenderer.setupDiskCache(codeCacheDir);
6194 RenderScriptCacheDir.setupDiskCache(codeCacheDir);
6195 }
6196 } catch (RemoteException e) {
6197 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6198 throw e.rethrowFromSystemServer();
6199 }
6200 } else {
6201 Log.w(TAG, "Unable to use shader/script cache: missing code-cache directory");
6202 }
6203 }
6204
6205 GraphicsEnvironment.getInstance().setup(context, mCoreSettings);
6206 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6207 }
6208
6209 private void updateDefaultDensity() {
6210 final int densityDpi = mCurDefaultDisplayDpi;
6211 if (!mDensityCompatMode
6212 && densityDpi != Configuration.DENSITY_DPI_UNDEFINED
6213 && densityDpi != DisplayMetrics.DENSITY_DEVICE) {
6214 DisplayMetrics.DENSITY_DEVICE = densityDpi;
6215 Bitmap.setDefaultDensity(densityDpi);
6216 }
6217 }
6218
6219 /**
6220 * Returns the correct library directory for the current ABI.
6221 * <p>
6222 * If we're dealing with a multi-arch application that has both 32 and 64 bit shared
6223 * libraries, we might need to choose the secondary depending on what the current
6224 * runtime's instruction set is.
6225 */
6226 private String getInstrumentationLibrary(ApplicationInfo appInfo, InstrumentationInfo insInfo) {
6227 if (appInfo.primaryCpuAbi != null && appInfo.secondaryCpuAbi != null
6228 && appInfo.secondaryCpuAbi.equals(insInfo.secondaryCpuAbi)) {
6229 // Get the instruction set supported by the secondary ABI. In the presence
6230 // of a native bridge this might be different than the one secondary ABI used.
6231 String secondaryIsa =
6232 VMRuntime.getInstructionSet(appInfo.secondaryCpuAbi);
6233 final String secondaryDexCodeIsa =
6234 SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
6235 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
6236
6237 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
6238 if (runtimeIsa.equals(secondaryIsa)) {
6239 return insInfo.secondaryNativeLibraryDir;
6240 }
6241 }
6242 return insInfo.nativeLibraryDir;
6243 }
6244
6245 /**
6246 * The LocaleList set for the app's resources may have been shuffled so that the preferred
6247 * Locale is at position 0. We must find the index of this preferred Locale in the
6248 * original LocaleList.
6249 */
6250 private void updateLocaleListFromAppContext(Context context, LocaleList newLocaleList) {
6251 final Locale bestLocale = context.getResources().getConfiguration().getLocales().get(0);
6252 final int newLocaleListSize = newLocaleList.size();
6253 for (int i = 0; i < newLocaleListSize; i++) {
6254 if (bestLocale.equals(newLocaleList.get(i))) {
6255 LocaleList.setDefault(newLocaleList, i);
6256 return;
6257 }
6258 }
6259
6260 // The app may have overridden the LocaleList with its own Locale
6261 // (not present in the available list). Push the chosen Locale
6262 // to the front of the list.
6263 LocaleList.setDefault(new LocaleList(bestLocale, newLocaleList));
6264 }
6265
6266 @UnsupportedAppUsage
6267 private void handleBindApplication(AppBindData data) {
6268 // Register the UI Thread as a sensitive thread to the runtime.
6269 VMRuntime.registerSensitiveThread();
6270 // In the case the stack depth property exists, pass it down to the runtime.
6271 String property = SystemProperties.get("debug.allocTracker.stackDepth");
6272 if (property.length() != 0) {
6273 VMDebug.setAllocTrackerStackDepth(Integer.parseInt(property));
6274 }
6275 if (data.trackAllocation) {
6276 DdmVmInternal.enableRecentAllocations(true);
6277 }
6278 // Note when this process has started.
6279 Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
6280
6281 AppCompatCallbacks.install(data.disabledCompatChanges);
6282 mBoundApplication = data;
6283 mConfiguration = new Configuration(data.config);
6284 mCompatConfiguration = new Configuration(data.config);
6285
6286 mProfiler = new Profiler();
6287 String agent = null;
6288 if (data.initProfilerInfo != null) {
6289 mProfiler.profileFile = data.initProfilerInfo.profileFile;
6290 mProfiler.profileFd = data.initProfilerInfo.profileFd;
6291 mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
6292 mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
6293 mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
6294 if (data.initProfilerInfo.attachAgentDuringBind) {
6295 agent = data.initProfilerInfo.agent;
6296 }
6297 }
6298
6299 // send up app name; do this *before* waiting for debugger
6300 Process.setArgV0(data.processName);
6301 android.ddm.DdmHandleAppName.setAppName(data.processName,
6302 data.appInfo.packageName,
6303 UserHandle.myUserId());
6304 VMRuntime.setProcessPackageName(data.appInfo.packageName);
6305
6306 // Pass data directory path to ART. This is used for caching information and
6307 // should be set before any application code is loaded.
6308 VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);
6309
6310 if (mProfiler.profileFd != null) {
6311 mProfiler.startProfiling();
6312 }
6313
6314 // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
6315 // implementation to use the pool executor. Normally, we use the
6316 // serialized executor as the default. This has to happen in the
6317 // main thread so the main looper is set right.
6318 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
6319 AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
6320 }
6321
6322 // Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier.
6323 UtilConfig.setThrowExceptionForUpperArrayOutOfBounds(
6324 data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);
6325
6326 Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
6327
6328 // Prior to P, internal calls to decode Bitmaps used BitmapFactory,
6329 // which may scale up to account for density. In P, we switched to
6330 // ImageDecoder, which skips the upscale to save memory. ImageDecoder
6331 // needs to still scale up in older apps, in case they rely on the
6332 // size of the Bitmap without considering its density.
6333 ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;
6334
6335 /*
6336 * Before spawning a new process, reset the time zone to be the system time zone.
6337 * This needs to be done because the system time zone could have changed after the
6338 * the spawning of this process. Without doing this this process would have the incorrect
6339 * system time zone.
6340 */
6341 TimeZone.setDefault(null);
6342
6343 /*
6344 * Set the LocaleList. This may change once we create the App Context.
6345 */
6346 LocaleList.setDefault(data.config.getLocales());
6347
6348 synchronized (mResourcesManager) {
6349 /*
6350 * Update the system configuration since its preloaded and might not
6351 * reflect configuration changes. The configuration object passed
6352 * in AppBindData can be safely assumed to be up to date
6353 */
6354 mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
6355 mCurDefaultDisplayDpi = data.config.densityDpi;
6356
6357 // This calls mResourcesManager so keep it within the synchronized block.
6358 applyCompatConfiguration(mCurDefaultDisplayDpi);
6359 }
6360
6361 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
6362
6363 if (agent != null) {
6364 handleAttachAgent(agent, data.info);
6365 }
6366
6367 /**
6368 * Switch this process to density compatibility mode if needed.
6369 */
6370 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
6371 == 0) {
6372 mDensityCompatMode = true;
6373 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
6374 }
6375 updateDefaultDensity();
6376
6377 final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
6378 Boolean is24Hr = null;
6379 if (use24HourSetting != null) {
6380 is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
6381 }
6382 // null : use locale default for 12/24 hour formatting,
6383 // false : use 12 hour format,
6384 // true : use 24 hour format.
6385 DateFormat.set24HourTimePref(is24Hr);
6386
6387 updateDebugViewAttributeState();
6388
6389 StrictMode.initThreadDefaults(data.appInfo);
6390 StrictMode.initVmDefaults(data.appInfo);
6391
6392 if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
6393 // XXX should have option to change the port.
6394 Debug.changeDebugPort(8100);
6395 if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
6396 Slog.w(TAG, "Application " + data.info.getPackageName()
6397 + " is waiting for the debugger on port 8100...");
6398
6399 IActivityManager mgr = ActivityManager.getService();
6400 try {
6401 mgr.showWaitingForDebugger(mAppThread, true);
6402 } catch (RemoteException ex) {
6403 throw ex.rethrowFromSystemServer();
6404 }
6405
6406 Debug.waitForDebugger();
6407
6408 try {
6409 mgr.showWaitingForDebugger(mAppThread, false);
6410 } catch (RemoteException ex) {
6411 throw ex.rethrowFromSystemServer();
6412 }
6413
6414 } else {
6415 Slog.w(TAG, "Application " + data.info.getPackageName()
6416 + " can be debugged on port 8100...");
6417 }
6418 }
6419
6420 // Allow binder tracing, and application-generated systrace messages if we're profileable.
6421 boolean isAppProfileable = data.appInfo.isProfileableByShell();
6422 Trace.setAppTracingAllowed(isAppProfileable);
6423 if (isAppProfileable && data.enableBinderTracking) {
6424 Binder.enableTracing();
6425 }
6426
6427 // Initialize heap profiling.
6428 if (isAppProfileable || Build.IS_DEBUGGABLE) {
6429 nInitZygoteChildHeapProfiling();
6430 }
6431
6432 // Allow renderer debugging features if we're debuggable.
6433 boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
6434 HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
6435 HardwareRenderer.setPackageName(data.appInfo.packageName);
6436
6437 /**
6438 * Initialize the default http proxy in this process for the reasons we set the time zone.
6439 */
6440 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
6441 final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
6442 if (b != null) {
6443 // In pre-boot mode (doing initial launch to collect password), not
6444 // all system is up. This includes the connectivity service, so don't
6445 // crash if we can't get it.
6446 final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
6447 try {
6448 Proxy.setHttpProxySystemProperty(service.getProxyForNetwork(null));
6449 } catch (RemoteException e) {
6450 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6451 throw e.rethrowFromSystemServer();
6452 }
6453 }
6454 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6455
6456 // Instrumentation info affects the class loader, so load it before
6457 // setting up the app context.
6458 final InstrumentationInfo ii;
6459 if (data.instrumentationName != null) {
6460 try {
6461 ii = new ApplicationPackageManager(
6462 null, getPackageManager(), getPermissionManager())
6463 .getInstrumentationInfo(data.instrumentationName, 0);
6464 } catch (PackageManager.NameNotFoundException e) {
6465 throw new RuntimeException(
6466 "Unable to find instrumentation info for: " + data.instrumentationName);
6467 }
6468
6469 // Warn of potential ABI mismatches.
6470 if (!Objects.equals(data.appInfo.primaryCpuAbi, ii.primaryCpuAbi)
6471 || !Objects.equals(data.appInfo.secondaryCpuAbi, ii.secondaryCpuAbi)) {
6472 Slog.w(TAG, "Package uses different ABI(s) than its instrumentation: "
6473 + "package[" + data.appInfo.packageName + "]: "
6474 + data.appInfo.primaryCpuAbi + ", " + data.appInfo.secondaryCpuAbi
6475 + " instrumentation[" + ii.packageName + "]: "
6476 + ii.primaryCpuAbi + ", " + ii.secondaryCpuAbi);
6477 }
6478
6479 mInstrumentationPackageName = ii.packageName;
6480 mInstrumentationAppDir = ii.sourceDir;
6481 mInstrumentationSplitAppDirs = ii.splitSourceDirs;
6482 mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
6483 mInstrumentedAppDir = data.info.getAppDir();
6484 mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
6485 mInstrumentedLibDir = data.info.getLibDir();
6486 } else {
6487 ii = null;
6488 }
6489
6490 final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
6491 updateLocaleListFromAppContext(appContext,
6492 mResourcesManager.getConfiguration().getLocales());
6493
6494 if (!Process.isIsolated()) {
6495 final int oldMask = StrictMode.allowThreadDiskWritesMask();
6496 try {
6497 setupGraphicsSupport(appContext);
6498 } finally {
6499 StrictMode.setThreadPolicyMask(oldMask);
6500 }
6501 } else {
6502 HardwareRenderer.setIsolatedProcess(true);
6503 }
6504
6505 // Install the Network Security Config Provider. This must happen before the application
6506 // code is loaded to prevent issues with instances of TLS objects being created before
6507 // the provider is installed.
6508 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
6509 NetworkSecurityConfigProvider.install(appContext);
6510 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6511
6512 // Continue loading instrumentation.
6513 if (ii != null) {
6514 ApplicationInfo instrApp;
6515 try {
6516 instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
6517 UserHandle.myUserId());
6518 } catch (RemoteException e) {
6519 instrApp = null;
6520 }
6521 if (instrApp == null) {
6522 instrApp = new ApplicationInfo();
6523 }
6524 ii.copyTo(instrApp);
6525 instrApp.initForUser(UserHandle.myUserId());
6526 final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
6527 appContext.getClassLoader(), false, true, false);
6528
6529 // The test context's op package name == the target app's op package name, because
6530 // the app ops manager checks the op package name against the real calling UID,
6531 // which is what the target package name is associated with.
6532 final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
6533 appContext.getOpPackageName());
6534
6535 try {
6536 final ClassLoader cl = instrContext.getClassLoader();
6537 mInstrumentation = (Instrumentation)
6538 cl.loadClass(data.instrumentationName.getClassName()).newInstance();
6539 } catch (Exception e) {
6540 throw new RuntimeException(
6541 "Unable to instantiate instrumentation "
6542 + data.instrumentationName + ": " + e.toString(), e);
6543 }
6544
6545 final ComponentName component = new ComponentName(ii.packageName, ii.name);
6546 mInstrumentation.init(this, instrContext, appContext, component,
6547 data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
6548
6549 if (mProfiler.profileFile != null && !ii.handleProfiling
6550 && mProfiler.profileFd == null) {
6551 mProfiler.handlingProfiling = true;
6552 final File file = new File(mProfiler.profileFile);
6553 file.getParentFile().mkdirs();
6554 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
6555 }
6556 } else {
6557 mInstrumentation = new Instrumentation();
6558 mInstrumentation.basicInit(this);
6559 }
6560
6561 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
6562 dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
6563 } else {
6564 // Small heap, clamp to the current growth limit and let the heap release
6565 // pages after the growth limit to the non growth limit capacity. b/18387825
6566 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
6567 }
6568
6569 // Allow disk access during application and provider setup. This could
6570 // block processing ordered broadcasts, but later processing would
6571 // probably end up doing the same disk access.
6572 Application app;
6573 final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
6574 final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
6575 try {
6576 // If the app is being launched for full backup or restore, bring it up in
6577 // a restricted environment with the base application class.
6578 app = data.info.makeApplication(data.restrictedBackupMode, null);
6579
6580 // Propagate autofill compat state
6581 app.setAutofillOptions(data.autofillOptions);
6582
6583 // Propagate Content Capture options
6584 app.setContentCaptureOptions(data.contentCaptureOptions);
6585
6586 mInitialApplication = app;
6587
6588 // don't bring up providers in restricted mode; they may depend on the
6589 // app's custom Application class
6590 if (!data.restrictedBackupMode) {
6591 if (!ArrayUtils.isEmpty(data.providers)) {
6592 installContentProviders(app, data.providers);
6593 }
6594 }
6595
6596 // Do this after providers, since instrumentation tests generally start their
6597 // test thread at this point, and we don't want that racing.
6598 try {
6599 mInstrumentation.onCreate(data.instrumentationArgs);
6600 }
6601 catch (Exception e) {
6602 throw new RuntimeException(
6603 "Exception thrown in onCreate() of "
6604 + data.instrumentationName + ": " + e.toString(), e);
6605 }
6606 try {
6607 mInstrumentation.callApplicationOnCreate(app);
6608 } catch (Exception e) {
6609 if (!mInstrumentation.onException(app, e)) {
6610 throw new RuntimeException(
6611 "Unable to create application " + app.getClass().getName()
6612 + ": " + e.toString(), e);
6613 }
6614 }
6615 } finally {
6616 // If the app targets < O-MR1, or doesn't change the thread policy
6617 // during startup, clobber the policy to maintain behavior of b/36951662
6618 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
6619 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
6620 StrictMode.setThreadPolicy(savedPolicy);
6621 }
6622 }
6623
6624 // Preload fonts resources
6625 FontsContract.setApplicationContextForResources(appContext);
6626 if (!Process.isIsolated()) {
6627 try {
6628 final ApplicationInfo info =
6629 getPackageManager().getApplicationInfo(
6630 data.appInfo.packageName,
6631 PackageManager.GET_META_DATA /*flags*/,
6632 UserHandle.myUserId());
6633 if (info.metaData != null) {
6634 final int preloadedFontsResource = info.metaData.getInt(
6635 ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
6636 if (preloadedFontsResource != 0) {
6637 data.info.getResources().preloadFonts(preloadedFontsResource);
6638 }
6639 }
6640 } catch (RemoteException e) {
6641 throw e.rethrowFromSystemServer();
6642 }
6643 }
6644 }
6645
6646 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
6647 IActivityManager am = ActivityManager.getService();
6648 if (mProfiler.profileFile != null && mProfiler.handlingProfiling
6649 && mProfiler.profileFd == null) {
6650 Debug.stopMethodTracing();
6651 }
6652 //Slog.i(TAG, "am: " + ActivityManager.getService()
6653 // + ", app thr: " + mAppThread);
6654 try {
6655 am.finishInstrumentation(mAppThread, resultCode, results);
6656 } catch (RemoteException ex) {
6657 throw ex.rethrowFromSystemServer();
6658 }
6659 }
6660
6661 @UnsupportedAppUsage
6662 private void installContentProviders(
6663 Context context, List<ProviderInfo> providers) {
6664 final ArrayList<ContentProviderHolder> results = new ArrayList<>();
6665
6666 for (ProviderInfo cpi : providers) {
6667 if (DEBUG_PROVIDER) {
6668 StringBuilder buf = new StringBuilder(128);
6669 buf.append("Pub ");
6670 buf.append(cpi.authority);
6671 buf.append(": ");
6672 buf.append(cpi.name);
6673 Log.i(TAG, buf.toString());
6674 }
6675 ContentProviderHolder cph = installProvider(context, null, cpi,
6676 false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
6677 if (cph != null) {
6678 cph.noReleaseNeeded = true;
6679 results.add(cph);
6680 }
6681 }
6682
6683 try {
6684 ActivityManager.getService().publishContentProviders(
6685 getApplicationThread(), results);
6686 } catch (RemoteException ex) {
6687 throw ex.rethrowFromSystemServer();
6688 }
6689 }
6690
6691 @UnsupportedAppUsage
6692 public final IContentProvider acquireProvider(
6693 Context c, String auth, int userId, boolean stable) {
6694 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
6695 if (provider != null) {
6696 return provider;
6697 }
6698
6699 // There is a possible race here. Another thread may try to acquire
6700 // the same provider at the same time. When this happens, we want to ensure
6701 // that the first one wins.
6702 // Note that we cannot hold the lock while acquiring and installing the
6703 // provider since it might take a long time to run and it could also potentially
6704 // be re-entrant in the case where the provider is in the same process.
6705 ContentProviderHolder holder = null;
6706 try {
6707 synchronized (getGetProviderLock(auth, userId)) {
6708 holder = ActivityManager.getService().getContentProvider(
6709 getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
6710 }
6711 } catch (RemoteException ex) {
6712 throw ex.rethrowFromSystemServer();
6713 }
6714 if (holder == null) {
6715 Slog.e(TAG, "Failed to find provider info for " + auth);
6716 return null;
6717 }
6718
6719 // Install provider will increment the reference count for us, and break
6720 // any ties in the race.
6721 holder = installProvider(c, holder, holder.info,
6722 true /*noisy*/, holder.noReleaseNeeded, stable);
6723 return holder.provider;
6724 }
6725
6726 private Object getGetProviderLock(String auth, int userId) {
6727 final ProviderKey key = new ProviderKey(auth, userId);
6728 synchronized (mGetProviderLocks) {
6729 Object lock = mGetProviderLocks.get(key);
6730 if (lock == null) {
6731 lock = key;
6732 mGetProviderLocks.put(key, lock);
6733 }
6734 return lock;
6735 }
6736 }
6737
6738 private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
6739 if (stable) {
6740 prc.stableCount += 1;
6741 if (prc.stableCount == 1) {
6742 // We are acquiring a new stable reference on the provider.
6743 int unstableDelta;
6744 if (prc.removePending) {
6745 // We have a pending remove operation, which is holding the
6746 // last unstable reference. At this point we are converting
6747 // that unstable reference to our new stable reference.
6748 unstableDelta = -1;
6749 // Cancel the removal of the provider.
6750 if (DEBUG_PROVIDER) {
6751 Slog.v(TAG, "incProviderRef: stable "
6752 + "snatched provider from the jaws of death");
6753 }
6754 prc.removePending = false;
6755 // There is a race! It fails to remove the message, which
6756 // will be handled in completeRemoveProvider().
6757 mH.removeMessages(H.REMOVE_PROVIDER, prc);
6758 } else {
6759 unstableDelta = 0;
6760 }
6761 try {
6762 if (DEBUG_PROVIDER) {
6763 Slog.v(TAG, "incProviderRef Now stable - "
6764 + prc.holder.info.name + ": unstableDelta="
6765 + unstableDelta);
6766 }
6767 ActivityManager.getService().refContentProvider(
6768 prc.holder.connection, 1, unstableDelta);
6769 } catch (RemoteException e) {
6770 //do nothing content provider object is dead any way
6771 }
6772 }
6773 } else {
6774 prc.unstableCount += 1;
6775 if (prc.unstableCount == 1) {
6776 // We are acquiring a new unstable reference on the provider.
6777 if (prc.removePending) {
6778 // Oh look, we actually have a remove pending for the
6779 // provider, which is still holding the last unstable
6780 // reference. We just need to cancel that to take new
6781 // ownership of the reference.
6782 if (DEBUG_PROVIDER) {
6783 Slog.v(TAG, "incProviderRef: unstable "
6784 + "snatched provider from the jaws of death");
6785 }
6786 prc.removePending = false;
6787 mH.removeMessages(H.REMOVE_PROVIDER, prc);
6788 } else {
6789 // First unstable ref, increment our count in the
6790 // activity manager.
6791 try {
6792 if (DEBUG_PROVIDER) {
6793 Slog.v(TAG, "incProviderRef: Now unstable - "
6794 + prc.holder.info.name);
6795 }
6796 ActivityManager.getService().refContentProvider(
6797 prc.holder.connection, 0, 1);
6798 } catch (RemoteException e) {
6799 //do nothing content provider object is dead any way
6800 }
6801 }
6802 }
6803 }
6804 }
6805
6806 @UnsupportedAppUsage
6807 public final IContentProvider acquireExistingProvider(
6808 Context c, String auth, int userId, boolean stable) {
6809 synchronized (mProviderMap) {
6810 final ProviderKey key = new ProviderKey(auth, userId);
6811 final ProviderClientRecord pr = mProviderMap.get(key);
6812 if (pr == null) {
6813 return null;
6814 }
6815
6816 IContentProvider provider = pr.mProvider;
6817 IBinder jBinder = provider.asBinder();
6818 if (!jBinder.isBinderAlive()) {
6819 // The hosting process of the provider has died; we can't
6820 // use this one.
6821 Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
6822 + ": existing object's process dead");
6823 handleUnstableProviderDiedLocked(jBinder, true);
6824 return null;
6825 }
6826
6827 // Only increment the ref count if we have one. If we don't then the
6828 // provider is not reference counted and never needs to be released.
6829 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6830 if (prc != null) {
6831 incProviderRefLocked(prc, stable);
6832 }
6833 return provider;
6834 }
6835 }
6836
6837 @UnsupportedAppUsage
6838 public final boolean releaseProvider(IContentProvider provider, boolean stable) {
6839 if (provider == null) {
6840 return false;
6841 }
6842
6843 IBinder jBinder = provider.asBinder();
6844 synchronized (mProviderMap) {
6845 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6846 if (prc == null) {
6847 // The provider has no ref count, no release is needed.
6848 return false;
6849 }
6850
6851 boolean lastRef = false;
6852 if (stable) {
6853 if (prc.stableCount == 0) {
6854 if (DEBUG_PROVIDER) Slog.v(TAG,
6855 "releaseProvider: stable ref count already 0, how?");
6856 return false;
6857 }
6858 prc.stableCount -= 1;
6859 if (prc.stableCount == 0) {
6860 // What we do at this point depends on whether there are
6861 // any unstable refs left: if there are, we just tell the
6862 // activity manager to decrement its stable count; if there
6863 // aren't, we need to enqueue this provider to be removed,
6864 // and convert to holding a single unstable ref while
6865 // doing so.
6866 lastRef = prc.unstableCount == 0;
6867 try {
6868 if (DEBUG_PROVIDER) {
6869 Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
6870 + lastRef + " - " + prc.holder.info.name);
6871 }
6872 ActivityManager.getService().refContentProvider(
6873 prc.holder.connection, -1, lastRef ? 1 : 0);
6874 } catch (RemoteException e) {
6875 //do nothing content provider object is dead any way
6876 }
6877 }
6878 } else {
6879 if (prc.unstableCount == 0) {
6880 if (DEBUG_PROVIDER) Slog.v(TAG,
6881 "releaseProvider: unstable ref count already 0, how?");
6882 return false;
6883 }
6884 prc.unstableCount -= 1;
6885 if (prc.unstableCount == 0) {
6886 // If this is the last reference, we need to enqueue
6887 // this provider to be removed instead of telling the
6888 // activity manager to remove it at this point.
6889 lastRef = prc.stableCount == 0;
6890 if (!lastRef) {
6891 try {
6892 if (DEBUG_PROVIDER) {
6893 Slog.v(TAG, "releaseProvider: No longer unstable - "
6894 + prc.holder.info.name);
6895 }
6896 ActivityManager.getService().refContentProvider(
6897 prc.holder.connection, 0, -1);
6898 } catch (RemoteException e) {
6899 //do nothing content provider object is dead any way
6900 }
6901 }
6902 }
6903 }
6904
6905 if (lastRef) {
6906 if (!prc.removePending) {
6907 // Schedule the actual remove asynchronously, since we don't know the context
6908 // this will be called in.
6909 if (DEBUG_PROVIDER) {
6910 Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
6911 + prc.holder.info.name);
6912 }
6913 prc.removePending = true;
6914 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
6915 mH.sendMessageDelayed(msg, CONTENT_PROVIDER_RETAIN_TIME);
6916 } else {
6917 Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
6918 }
6919 }
6920 return true;
6921 }
6922 }
6923
6924 final void completeRemoveProvider(ProviderRefCount prc) {
6925 synchronized (mProviderMap) {
6926 if (!prc.removePending) {
6927 // There was a race! Some other client managed to acquire
6928 // the provider before the removal was completed.
6929 // Abort the removal. We will do it later.
6930 if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
6931 + "provider still in use");
6932 return;
6933 }
6934
6935 // More complicated race!! Some client managed to acquire the
6936 // provider and release it before the removal was completed.
6937 // Continue the removal, and abort the next remove message.
6938 prc.removePending = false;
6939
6940 final IBinder jBinder = prc.holder.provider.asBinder();
6941 ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
6942 if (existingPrc == prc) {
6943 mProviderRefCountMap.remove(jBinder);
6944 }
6945
6946 for (int i=mProviderMap.size()-1; i>=0; i--) {
6947 ProviderClientRecord pr = mProviderMap.valueAt(i);
6948 IBinder myBinder = pr.mProvider.asBinder();
6949 if (myBinder == jBinder) {
6950 mProviderMap.removeAt(i);
6951 }
6952 }
6953 }
6954
6955 try {
6956 if (DEBUG_PROVIDER) {
6957 Slog.v(TAG, "removeProvider: Invoking ActivityManagerService."
6958 + "removeContentProvider(" + prc.holder.info.name + ")");
6959 }
6960 ActivityManager.getService().removeContentProvider(
6961 prc.holder.connection, false);
6962 } catch (RemoteException e) {
6963 //do nothing content provider object is dead any way
6964 }
6965 }
6966
6967 @UnsupportedAppUsage
6968 final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
6969 synchronized (mProviderMap) {
6970 handleUnstableProviderDiedLocked(provider, fromClient);
6971 }
6972 }
6973
6974 final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
6975 ProviderRefCount prc = mProviderRefCountMap.get(provider);
6976 if (prc != null) {
6977 if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
6978 + provider + " " + prc.holder.info.name);
6979 mProviderRefCountMap.remove(provider);
6980 for (int i=mProviderMap.size()-1; i>=0; i--) {
6981 ProviderClientRecord pr = mProviderMap.valueAt(i);
6982 if (pr != null && pr.mProvider.asBinder() == provider) {
6983 Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString());
6984 mProviderMap.removeAt(i);
6985 }
6986 }
6987
6988 if (fromClient) {
6989 // We found out about this due to execution in our client
6990 // code. Tell the activity manager about it now, to ensure
6991 // that the next time we go to do anything with the provider
6992 // it knows it is dead (so we don't race with its death
6993 // notification).
6994 try {
6995 ActivityManager.getService().unstableProviderDied(
6996 prc.holder.connection);
6997 } catch (RemoteException e) {
6998 //do nothing content provider object is dead any way
6999 }
7000 }
7001 }
7002 }
7003
7004 final void appNotRespondingViaProvider(IBinder provider) {
7005 synchronized (mProviderMap) {
7006 ProviderRefCount prc = mProviderRefCountMap.get(provider);
7007 if (prc != null) {
7008 try {
7009 ActivityManager.getService()
7010 .appNotRespondingViaProvider(prc.holder.connection);
7011 } catch (RemoteException e) {
7012 throw e.rethrowFromSystemServer();
7013 }
7014 }
7015 }
7016 }
7017
7018 private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
7019 ContentProvider localProvider, ContentProviderHolder holder) {
7020 final String auths[] = holder.info.authority.split(";");
7021 final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
7022
7023 if (provider != null) {
7024 // If this provider is hosted by the core OS and cannot be upgraded,
7025 // then I guess we're okay doing blocking calls to it.
7026 for (String auth : auths) {
7027 switch (auth) {
7028 case ContactsContract.AUTHORITY:
7029 case CallLog.AUTHORITY:
7030 case CallLog.SHADOW_AUTHORITY:
7031 case BlockedNumberContract.AUTHORITY:
7032 case CalendarContract.AUTHORITY:
7033 case Downloads.Impl.AUTHORITY:
7034 case "telephony":
7035 Binder.allowBlocking(provider.asBinder());
7036 }
7037 }
7038 }
7039
7040 final ProviderClientRecord pcr = new ProviderClientRecord(
7041 auths, provider, localProvider, holder);
7042 for (String auth : auths) {
7043 final ProviderKey key = new ProviderKey(auth, userId);
7044 final ProviderClientRecord existing = mProviderMap.get(key);
7045 if (existing != null) {
7046 Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
7047 + " already published as " + auth);
7048 } else {
7049 mProviderMap.put(key, pcr);
7050 }
7051 }
7052 return pcr;
7053 }
7054
7055 /**
7056 * Installs the provider.
7057 *
7058 * Providers that are local to the process or that come from the system server
7059 * may be installed permanently which is indicated by setting noReleaseNeeded to true.
7060 * Other remote providers are reference counted. The initial reference count
7061 * for all reference counted providers is one. Providers that are not reference
7062 * counted do not have a reference count (at all).
7063 *
7064 * This method detects when a provider has already been installed. When this happens,
7065 * it increments the reference count of the existing provider (if appropriate)
7066 * and returns the existing provider. This can happen due to concurrent
7067 * attempts to acquire the same provider.
7068 */
7069 @UnsupportedAppUsage
7070 private ContentProviderHolder installProvider(Context context,
7071 ContentProviderHolder holder, ProviderInfo info,
7072 boolean noisy, boolean noReleaseNeeded, boolean stable) {
7073 ContentProvider localProvider = null;
7074 IContentProvider provider;
7075 if (holder == null || holder.provider == null) {
7076 if (DEBUG_PROVIDER || noisy) {
7077 Slog.d(TAG, "Loading provider " + info.authority + ": "
7078 + info.name);
7079 }
7080 Context c = null;
7081 ApplicationInfo ai = info.applicationInfo;
7082 if (context.getPackageName().equals(ai.packageName)) {
7083 c = context;
7084 } else if (mInitialApplication != null &&
7085 mInitialApplication.getPackageName().equals(ai.packageName)) {
7086 c = mInitialApplication;
7087 } else {
7088 try {
7089 c = context.createPackageContext(ai.packageName,
7090 Context.CONTEXT_INCLUDE_CODE);
7091 } catch (PackageManager.NameNotFoundException e) {
7092 // Ignore
7093 }
7094 }
7095 if (c == null) {
7096 Slog.w(TAG, "Unable to get context for package " +
7097 ai.packageName +
7098 " while loading content provider " +
7099 info.name);
7100 return null;
7101 }
7102
7103 if (info.splitName != null) {
7104 try {
7105 c = c.createContextForSplit(info.splitName);
7106 } catch (NameNotFoundException e) {
7107 throw new RuntimeException(e);
7108 }
7109 }
7110
7111 try {
7112 final java.lang.ClassLoader cl = c.getClassLoader();
7113 LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
7114 if (packageInfo == null) {
7115 // System startup case.
7116 packageInfo = getSystemContext().mPackageInfo;
7117 }
7118 localProvider = packageInfo.getAppFactory()
7119 .instantiateProvider(cl, info.name);
7120 provider = localProvider.getIContentProvider();
7121 if (provider == null) {
7122 Slog.e(TAG, "Failed to instantiate class " +
7123 info.name + " from sourceDir " +
7124 info.applicationInfo.sourceDir);
7125 return null;
7126 }
7127 if (DEBUG_PROVIDER) Slog.v(
7128 TAG, "Instantiating local provider " + info.name);
7129 // XXX Need to create the correct context for this provider.
7130 localProvider.attachInfo(c, info);
7131 } catch (java.lang.Exception e) {
7132 if (!mInstrumentation.onException(null, e)) {
7133 throw new RuntimeException(
7134 "Unable to get provider " + info.name
7135 + ": " + e.toString(), e);
7136 }
7137 return null;
7138 }
7139 } else {
7140 provider = holder.provider;
7141 if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
7142 + info.name);
7143 }
7144
7145 ContentProviderHolder retHolder;
7146
7147 synchronized (mProviderMap) {
7148 if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
7149 + " / " + info.name);
7150 IBinder jBinder = provider.asBinder();
7151 if (localProvider != null) {
7152 ComponentName cname = new ComponentName(info.packageName, info.name);
7153 ProviderClientRecord pr = mLocalProvidersByName.get(cname);
7154 if (pr != null) {
7155 if (DEBUG_PROVIDER) {
7156 Slog.v(TAG, "installProvider: lost the race, "
7157 + "using existing local provider");
7158 }
7159 provider = pr.mProvider;
7160 } else {
7161 holder = new ContentProviderHolder(info);
7162 holder.provider = provider;
7163 holder.noReleaseNeeded = true;
7164 pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
7165 mLocalProviders.put(jBinder, pr);
7166 mLocalProvidersByName.put(cname, pr);
7167 }
7168 retHolder = pr.mHolder;
7169 } else {
7170 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
7171 if (prc != null) {
7172 if (DEBUG_PROVIDER) {
7173 Slog.v(TAG, "installProvider: lost the race, updating ref count");
7174 }
7175 // We need to transfer our new reference to the existing
7176 // ref count, releasing the old one... but only if
7177 // release is needed (that is, it is not running in the
7178 // system process).
7179 if (!noReleaseNeeded) {
7180 incProviderRefLocked(prc, stable);
7181 try {
7182 ActivityManager.getService().removeContentProvider(
7183 holder.connection, stable);
7184 } catch (RemoteException e) {
7185 //do nothing content provider object is dead any way
7186 }
7187 }
7188 } else {
7189 ProviderClientRecord client = installProviderAuthoritiesLocked(
7190 provider, localProvider, holder);
7191 if (noReleaseNeeded) {
7192 prc = new ProviderRefCount(holder, client, 1000, 1000);
7193 } else {
7194 prc = stable
7195 ? new ProviderRefCount(holder, client, 1, 0)
7196 : new ProviderRefCount(holder, client, 0, 1);
7197 }
7198 mProviderRefCountMap.put(jBinder, prc);
7199 }
7200 retHolder = prc.holder;
7201 }
7202 }
7203 return retHolder;
7204 }
7205
7206 private void handleRunIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
7207 try {
7208 Method main = Class.forName(entryPoint).getMethod("main", String[].class);
7209 main.invoke(null, new Object[]{entryPointArgs});
7210 } catch (ReflectiveOperationException e) {
7211 throw new AndroidRuntimeException("runIsolatedEntryPoint failed", e);
7212 }
7213 // The process will be empty after this method returns; exit the VM now.
7214 System.exit(0);
7215 }
7216
7217 @UnsupportedAppUsage
7218 private void attach(boolean system, long startSeq) {
7219 sCurrentActivityThread = this;
7220 mSystemThread = system;
7221 if (!system) {
7222 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
7223 UserHandle.myUserId());
7224 RuntimeInit.setApplicationObject(mAppThread.asBinder());
7225 final IActivityManager mgr = ActivityManager.getService();
7226 try {
7227 mgr.attachApplication(mAppThread, startSeq);
7228 } catch (RemoteException ex) {
7229 throw ex.rethrowFromSystemServer();
7230 }
7231 // Watch for getting close to heap limit.
7232 BinderInternal.addGcWatcher(new Runnable() {
7233 @Override public void run() {
7234 if (!mSomeActivitiesChanged) {
7235 return;
7236 }
7237 Runtime runtime = Runtime.getRuntime();
7238 long dalvikMax = runtime.maxMemory();
7239 long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
7240 if (dalvikUsed > ((3*dalvikMax)/4)) {
7241 if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
7242 + " total=" + (runtime.totalMemory()/1024)
7243 + " used=" + (dalvikUsed/1024));
7244 mSomeActivitiesChanged = false;
7245 try {
7246 ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
7247 } catch (RemoteException e) {
7248 throw e.rethrowFromSystemServer();
7249 }
7250 }
7251 }
7252 });
7253 } else {
7254 // Don't set application object here -- if the system crashes,
7255 // we can't display an alert, we just want to die die die.
7256 android.ddm.DdmHandleAppName.setAppName("system_process",
7257 UserHandle.myUserId());
7258 try {
7259 mInstrumentation = new Instrumentation();
7260 mInstrumentation.basicInit(this);
7261 ContextImpl context = ContextImpl.createAppContext(
7262 this, getSystemContext().mPackageInfo);
7263 mInitialApplication = context.mPackageInfo.makeApplication(true, null);
7264 mInitialApplication.onCreate();
7265 } catch (Exception e) {
7266 throw new RuntimeException(
7267 "Unable to instantiate Application():" + e.toString(), e);
7268 }
7269 }
7270
7271 ViewRootImpl.ConfigChangedCallback configChangedCallback
7272 = (Configuration globalConfig) -> {
7273 synchronized (mResourcesManager) {
7274 // TODO (b/135719017): Temporary log for debugging IME service.
7275 if (Build.IS_DEBUGGABLE && mHasImeComponent) {
7276 Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
7277 + "config=" + globalConfig);
7278 }
7279
7280 // We need to apply this change to the resources immediately, because upon returning
7281 // the view hierarchy will be informed about it.
7282 if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
7283 null /* compat */)) {
7284 updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
7285 mResourcesManager.getConfiguration().getLocales());
7286
7287 // This actually changed the resources! Tell everyone about it.
7288 if (mPendingConfiguration == null
7289 || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
7290 mPendingConfiguration = globalConfig;
7291 sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
7292 }
7293 }
7294 }
7295 };
7296 ViewRootImpl.addConfigCallback(configChangedCallback);
7297 }
7298
7299 @UnsupportedAppUsage
7300 public static ActivityThread systemMain() {
7301 // The system process on low-memory devices do not get to use hardware
7302 // accelerated drawing, since this can add too much overhead to the
7303 // process.
7304 if (!ActivityManager.isHighEndGfx()) {
7305 ThreadedRenderer.disable(true);
7306 } else {
7307 ThreadedRenderer.enableForegroundTrimming();
7308 }
7309 ActivityThread thread = new ActivityThread();
7310 thread.attach(true, 0);
7311 return thread;
7312 }
7313
7314 public static void updateHttpProxy(@NonNull Context context) {
7315 final ConnectivityManager cm = ConnectivityManager.from(context);
7316 Proxy.setHttpProxySystemProperty(cm.getDefaultProxy());
7317 }
7318
7319 @UnsupportedAppUsage
7320 public final void installSystemProviders(List<ProviderInfo> providers) {
7321 if (providers != null) {
7322 installContentProviders(mInitialApplication, providers);
7323 }
7324 }
7325
7326 public int getIntCoreSetting(String key, int defaultValue) {
7327 synchronized (mResourcesManager) {
7328 if (mCoreSettings != null) {
7329 return mCoreSettings.getInt(key, defaultValue);
7330 }
7331 return defaultValue;
7332 }
7333 }
7334
7335 float getFloatCoreSetting(String key, float defaultValue) {
7336 synchronized (mResourcesManager) {
7337 if (mCoreSettings != null) {
7338 return mCoreSettings.getFloat(key, defaultValue);
7339 }
7340 return defaultValue;
7341 }
7342 }
7343
7344 private static class AndroidOs extends ForwardingOs {
7345 /**
7346 * Install selective syscall interception. For example, this is used to
7347 * implement special filesystem paths that will be redirected to
7348 * {@link ContentResolver#openFileDescriptor(Uri, String)}.
7349 */
7350 public static void install() {
7351 // If feature is disabled, we don't need to install
7352 if (!DEPRECATE_DATA_COLUMNS) return;
7353
7354 // Install interception and make sure it sticks!
7355 Os def = null;
7356 do {
7357 def = Os.getDefault();
7358 } while (!Os.compareAndSetDefault(def, new AndroidOs(def)));
7359 }
7360
7361 private AndroidOs(Os os) {
7362 super(os);
7363 }
7364
7365 private FileDescriptor openDeprecatedDataPath(String path, int mode) throws ErrnoException {
7366 final Uri uri = ContentResolver.translateDeprecatedDataPath(path);
7367 Log.v(TAG, "Redirecting " + path + " to " + uri);
7368
7369 final ContentResolver cr = currentActivityThread().getApplication()
7370 .getContentResolver();
7371 try {
7372 final FileDescriptor fd = new FileDescriptor();
7373 fd.setInt$(cr.openFileDescriptor(uri,
7374 FileUtils.translateModePosixToString(mode)).detachFd());
7375 return fd;
7376 } catch (SecurityException e) {
7377 throw new ErrnoException(e.getMessage(), OsConstants.EACCES);
7378 } catch (FileNotFoundException e) {
7379 throw new ErrnoException(e.getMessage(), OsConstants.ENOENT);
7380 }
7381 }
7382
7383 private void deleteDeprecatedDataPath(String path) throws ErrnoException {
7384 final Uri uri = ContentResolver.translateDeprecatedDataPath(path);
7385 Log.v(TAG, "Redirecting " + path + " to " + uri);
7386
7387 final ContentResolver cr = currentActivityThread().getApplication()
7388 .getContentResolver();
7389 try {
7390 if (cr.delete(uri, null, null) == 0) {
7391 throw new FileNotFoundException();
7392 }
7393 } catch (SecurityException e) {
7394 throw new ErrnoException(e.getMessage(), OsConstants.EACCES);
7395 } catch (FileNotFoundException e) {
7396 throw new ErrnoException(e.getMessage(), OsConstants.ENOENT);
7397 }
7398 }
7399
7400 @Override
7401 public boolean access(String path, int mode) throws ErrnoException {
7402 if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
7403 // If we opened it okay, then access check succeeded
7404 IoUtils.closeQuietly(
7405 openDeprecatedDataPath(path, FileUtils.translateModeAccessToPosix(mode)));
7406 return true;
7407 } else {
7408 return super.access(path, mode);
7409 }
7410 }
7411
7412 @Override
7413 public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
7414 if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
7415 return openDeprecatedDataPath(path, mode);
7416 } else {
7417 return super.open(path, flags, mode);
7418 }
7419 }
7420
7421 @Override
7422 public StructStat stat(String path) throws ErrnoException {
7423 if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
7424 final FileDescriptor fd = openDeprecatedDataPath(path, OsConstants.O_RDONLY);
7425 try {
7426 return android.system.Os.fstat(fd);
7427 } finally {
7428 IoUtils.closeQuietly(fd);
7429 }
7430 } else {
7431 return super.stat(path);
7432 }
7433 }
7434
7435 @Override
7436 public void unlink(String path) throws ErrnoException {
7437 if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
7438 deleteDeprecatedDataPath(path);
7439 } else {
7440 super.unlink(path);
7441 }
7442 }
7443
7444 @Override
7445 public void remove(String path) throws ErrnoException {
7446 if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
7447 deleteDeprecatedDataPath(path);
7448 } else {
7449 super.remove(path);
7450 }
7451 }
7452
7453 @Override
7454 public void rename(String oldPath, String newPath) throws ErrnoException {
7455 try {
7456 super.rename(oldPath, newPath);
7457 } catch (ErrnoException e) {
7458 if (e.errno == OsConstants.EXDEV && oldPath.startsWith("/storage/")) {
7459 Log.v(TAG, "Recovering failed rename " + oldPath + " to " + newPath);
7460 try {
7461 Files.move(new File(oldPath).toPath(), new File(newPath).toPath(),
7462 StandardCopyOption.REPLACE_EXISTING);
7463 } catch (IOException e2) {
7464 Log.e(TAG, "Rename recovery failed ", e);
7465 throw e;
7466 }
7467 } else {
7468 throw e;
7469 }
7470 }
7471 }
7472 }
7473
7474 public static void main(String[] args) {
7475 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
7476
7477 // Install selective syscall interception
7478 AndroidOs.install();
7479
7480 // CloseGuard defaults to true and can be quite spammy. We
7481 // disable it here, but selectively enable it later (via
7482 // StrictMode) on debug builds, but using DropBox, not logs.
7483 CloseGuard.setEnabled(false);
7484
7485 Environment.initForCurrentUser();
7486
7487 // Make sure TrustedCertificateStore looks in the right place for CA certificates
7488 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
7489 TrustedCertificateStore.setDefaultUserDirectory(configDir);
7490
7491 // Call per-process mainline module initialization.
7492 initializeMainlineModules();
7493
7494 Process.setArgV0("<pre-initialized>");
7495
7496 Looper.prepareMainLooper();
7497
7498 // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
7499 // It will be in the format "seq=114"
7500 long startSeq = 0;
7501 if (args != null) {
7502 for (int i = args.length - 1; i >= 0; --i) {
7503 if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
7504 startSeq = Long.parseLong(
7505 args[i].substring(PROC_START_SEQ_IDENT.length()));
7506 }
7507 }
7508 }
7509 ActivityThread thread = new ActivityThread();
7510 thread.attach(false, startSeq);
7511
7512 if (sMainThreadHandler == null) {
7513 sMainThreadHandler = thread.getHandler();
7514 }
7515
7516 if (false) {
7517 Looper.myLooper().setMessageLogging(new
7518 LogPrinter(Log.DEBUG, "ActivityThread"));
7519 }
7520
7521 // End of event ActivityThreadMain.
7522 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
7523 Looper.loop();
7524
7525 throw new RuntimeException("Main thread loop unexpectedly exited");
7526 }
7527
7528 /**
7529 * Call various initializer APIs in mainline modules that need to be called when each process
7530 * starts.
7531 */
7532 public static void initializeMainlineModules() {
7533 TelephonyFrameworkInitializer.setTelephonyServiceManager(new TelephonyServiceManager());
7534 StatsFrameworkInitializer.setStatsServiceManager(new StatsServiceManager());
7535 }
7536
7537 private void purgePendingResources() {
7538 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "purgePendingResources");
7539 nPurgePendingResources();
7540 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
7541 }
7542
7543 // ------------------ Regular JNI ------------------------
7544 private native void nPurgePendingResources();
7545 private native void nDumpGraphicsInfo(FileDescriptor fd);
7546 private native void nInitZygoteChildHeapProfiling();
7547}