Merge "Validate content overlay before removal" into tm-dev
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 51ed856..f7c2b73 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1879,12 +1879,6 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/TaskFragment.java"
     },
-    "-240296576": {
-      "message": "handleAppTransitionReady: displayId=%d appTransition={%s} openingApps=[%s] closingApps=[%s] transit=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
     "-237664290": {
       "message": "Pause the recording session on display %s",
       "level": "VERBOSE",
@@ -1987,6 +1981,12 @@
       "group": "WM_DEBUG_CONTENT_RECORDING",
       "at": "com\/android\/server\/wm\/ContentRecorder.java"
     },
+    "-134793542": {
+      "message": "handleAppTransitionReady: displayId=%d appTransition={%s} excludeLauncherFromAnimation=%b openingApps=[%s] closingApps=[%s] transit=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/AppTransitionController.java"
+    },
     "-134091882": {
       "message": "Screenshotting Activity %s",
       "level": "VERBOSE",
@@ -2491,12 +2491,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "323235828": {
-      "message": "Delaying app transition for recents animation to finish",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
     "327461496": {
       "message": "Complete pause: %s",
       "level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index a089585..b8bf1a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -706,6 +706,8 @@
      * @param animate whether the pointer should animate to this position.
      */
     public void setPointerPosition(float bubblePosition, boolean onLeft, boolean animate) {
+        final boolean isRtl = mContext.getResources().getConfiguration().getLayoutDirection()
+                == LAYOUT_DIRECTION_RTL;
         // Pointer gets drawn in the padding
         final boolean showVertically = mPositioner.showBubblesVertically();
         final float paddingLeft = (showVertically && onLeft)
@@ -732,12 +734,22 @@
             float pointerX;
             if (showVertically) {
                 pointerY = bubbleCenter - (mPointerWidth / 2f);
-                pointerX = onLeft
-                        ? -mPointerHeight + mPointerOverlap
-                        : getWidth() - mPaddingRight - mPointerOverlap;
+                if (!isRtl) {
+                    pointerX = onLeft
+                            ? -mPointerHeight + mPointerOverlap
+                            : getWidth() - mPaddingRight - mPointerOverlap;
+                } else {
+                    pointerX = onLeft
+                            ? -(getWidth() - mPaddingLeft - mPointerOverlap)
+                            : mPointerHeight - mPointerOverlap;
+                }
             } else {
                 pointerY = mPointerOverlap;
-                pointerX = bubbleCenter - (mPointerWidth / 2f);
+                if (!isRtl) {
+                    pointerX = bubbleCenter - (mPointerWidth / 2f);
+                } else {
+                    pointerX = -(getWidth() - mPaddingLeft - bubbleCenter) + (mPointerWidth / 2f);
+                }
             }
             if (animate) {
                 mPointerView.animate().translationX(pointerX).translationY(pointerY).start();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a2106f9..e639b29 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -128,6 +128,10 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
 import static com.android.server.am.ProcessList.ProcStartHandler;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_BACKUP;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_INSTRUMENTATION;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_PERSISTENT;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_SYSTEM;
 import static com.android.server.net.NetworkPolicyManagerInternal.updateBlockedReasonsWithProcState;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
@@ -1877,6 +1881,7 @@
                 app.setPid(MY_PID);
                 app.mState.setMaxAdj(ProcessList.SYSTEM_ADJ);
                 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
+                app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_SYSTEM);
                 addPidLocked(app);
                 updateLruProcessLocked(app, false, null);
                 updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -4179,7 +4184,9 @@
                                     mi.getTotalRss(),
                                     ProcessStats.ADD_PSS_EXTERNAL_SLOW,
                                     duration,
-                                    holder.appVersion);
+                                    holder.appVersion,
+                                    profile.getCurrentHostingComponentTypes(),
+                                    profile.getHistoricalHostingComponentTypes());
                         });
                     }
                 }
@@ -4237,7 +4244,9 @@
                                     tmpUss[2],
                                     ProcessStats.ADD_PSS_EXTERNAL,
                                     duration,
-                                    holder.appVersion);
+                                    holder.appVersion,
+                                    profile.getCurrentHostingComponentTypes(),
+                                    profile.getHistoricalHostingComponentTypes());
                         });
                     }
                 }
@@ -6416,8 +6425,13 @@
                         .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
                 for (ApplicationInfo app : apps) {
                     if (!"android".equals(app.packageName)) {
-                        addAppLocked(app, null, false, null /* ABI override */,
+                        final ProcessRecord proc = addAppLocked(
+                                app, null, false, null /* ABI override */,
                                 ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
+                        if (proc != null) {
+                            proc.mProfile.addHostingComponentType(
+                                    HOSTING_COMPONENT_TYPE_PERSISTENT);
+                        }
                     }
                 }
             } catch (RemoteException ex) {
@@ -11295,7 +11309,9 @@
                                     holder.state.getPackage(),
                                     myTotalPss, myTotalUss, myTotalRss, reportType,
                                     endTime-startTime,
-                                    holder.appVersion);
+                                    holder.appVersion,
+                                    r.mProfile.getCurrentHostingComponentTypes(),
+                                    r.mProfile.getHistoricalHostingComponentTypes());
                         });
                     }
                 }
@@ -11938,7 +11954,9 @@
                                 holder.state.getName(),
                                 holder.state.getPackage(),
                                 myTotalPss, myTotalUss, myTotalRss, reportType, endTime-startTime,
-                                holder.appVersion);
+                                holder.appVersion,
+                                r.mProfile.getCurrentHostingComponentTypes(),
+                                r.mProfile.getHistoricalHostingComponentTypes());
                     });
                 }
             }
@@ -12772,6 +12790,8 @@
             newBackupUid = proc.isInFullBackup() ? r.appInfo.uid : -1;
             mBackupTargets.put(targetUserId, r);
 
+            proc.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_BACKUP);
+
             // Try not to kill the process during backup
             updateOomAdjLocked(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
 
@@ -12814,7 +12834,15 @@
         }
 
         synchronized (this) {
-            mBackupTargets.delete(userId);
+            final int indexOfKey = mBackupTargets.indexOfKey(userId);
+            if (indexOfKey >= 0) {
+                final BackupRecord backupTarget = mBackupTargets.valueAt(indexOfKey);
+                if (backupTarget != null && backupTarget.app != null) {
+                    backupTarget.app.mProfile.clearHostingComponentType(
+                            HOSTING_COMPONENT_TYPE_BACKUP);
+                }
+                mBackupTargets.removeAt(indexOfKey);
+            }
         }
 
         JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
@@ -12892,6 +12920,7 @@
                 final ProcessRecord proc = backupTarget.app;
                 updateOomAdjLocked(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
                 proc.setInFullBackup(false);
+                proc.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_BACKUP);
 
                 oldBackupUid = backupTarget != null ? backupTarget.appInfo.uid : -1;
 
@@ -14620,6 +14649,7 @@
                     }
                     app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
                             disableTestApiChecks, abiOverride, ZYGOTE_POLICY_FLAG_EMPTY);
+                    app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_INSTRUMENTATION);
                 }
 
                 app.setActiveInstrumentation(activeInstr);
@@ -14744,6 +14774,7 @@
                 if (!mActiveInstrumentation.contains(activeInstr)) {
                     mActiveInstrumentation.add(activeInstr);
                 }
+                app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_INSTRUMENTATION);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -14873,6 +14904,7 @@
             instr.removeProcess(app);
             app.setActiveInstrumentation(null);
         }
+        app.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_INSTRUMENTATION);
 
         if (app.isSdkSandbox) {
             // For sharedUid apps this will kill all sdk sandbox processes, which is not ideal.
@@ -15753,6 +15785,7 @@
                 if (app.isPersistent()) {
                     addAppLocked(app.info, null, false, null /* ABI override */,
                             ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
+                    app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_PERSISTENT);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 16a7283..61d8568 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -573,7 +573,9 @@
                     holder.state.getPackage(),
                     pss, uss, rss,
                     statType, pssDuration,
-                    holder.appVersion);
+                    holder.appVersion,
+                    profile.getCurrentHostingComponentTypes(),
+                    profile.getHistoricalHostingComponentTypes());
         });
         if (DEBUG_PSS) {
             Slog.d(TAG_PSS,
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 24e815e..7289331 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -24,6 +24,7 @@
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
 import static com.android.server.am.ActivityManagerService.TAG_MU;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_PROVIDER;
 
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -701,6 +702,9 @@
                     dst.onProviderPublishStatusLocked(true);
                 }
                 dst.mRestartCount = 0;
+                if (hasProviderConnectionLocked(r)) {
+                    r.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_PROVIDER);
+                }
             }
 
             // update the app's oom adj value and each provider's usage stats
@@ -1375,6 +1379,9 @@
         conn.startAssociationIfNeeded();
         conn.initializeCount(stable);
         cpr.connections.add(conn);
+        if (cpr.proc != null) {
+            cpr.proc.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_PROVIDER);
+        }
         pr.addProviderConnection(conn);
         mService.startAssociationLocked(r.uid, r.processName, r.mState.getCurProcState(),
                 cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
@@ -1418,6 +1425,16 @@
         return true;
     }
 
+    @GuardedBy("mService")
+    private boolean hasProviderConnectionLocked(ProcessRecord proc) {
+        for (int i = proc.mProviders.numberOfProviders() - 1; i >= 0; i--) {
+            if (!proc.mProviders.getProviderAt(i).connections.isEmpty()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void handleProviderRemoval(ContentProviderConnection conn, boolean stable,
             boolean updateOomAdj) {
         synchronized (mService) {
@@ -1429,6 +1446,9 @@
             final ContentProviderRecord cpr = conn.provider;
             conn.stopAssociation();
             cpr.connections.remove(conn);
+            if (cpr.proc != null && !hasProviderConnectionLocked(cpr.proc)) {
+                cpr.proc.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_PROVIDER);
+            }
             conn.client.mProviders.removeProviderConnection(conn);
             if (conn.client.mState.getSetProcState()
                     < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
@@ -1737,6 +1757,9 @@
                 // In the protocol here, we don't expect the client to correctly
                 // clean up this connection, we'll just remove it.
                 cpr.connections.remove(i);
+                if (cpr.proc != null && !hasProviderConnectionLocked(cpr.proc)) {
+                    cpr.proc.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_PROVIDER);
+                }
                 if (conn.client.mProviders.removeProviderConnection(conn)) {
                     mService.stopAssociationLocked(capp.uid, capp.processName,
                             cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index 50970b5..cee34d5 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityManager.processStateAmToProto;
 
+import android.annotation.IntDef;
 import android.app.IApplicationThread;
 import android.content.pm.ApplicationInfo;
 import android.os.Debug;
@@ -35,12 +36,95 @@
 import com.android.server.am.ProcessList.ProcStateMemTracker;
 
 import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Profiling info of the process, such as PSS, cpu, etc.
  */
 final class ProcessProfileRecord {
+    // Keep below types in sync with the HostingComponentType in the atoms.proto.
+    /**
+     * The type of the component this process is hosting;
+     * this means not hosting any components (cached).
+     */
+    static final int HOSTING_COMPONENT_TYPE_EMPTY = 0x0;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's a system process.
+     */
+    static final int HOSTING_COMPONENT_TYPE_SYSTEM = 0x00000001;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's a persistent process.
+     */
+    static final int HOSTING_COMPONENT_TYPE_PERSISTENT = 0x00000002;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting a backup/restore agent.
+     */
+    static final int HOSTING_COMPONENT_TYPE_BACKUP = 0x00000004;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting an instrumentation.
+     */
+    static final int HOSTING_COMPONENT_TYPE_INSTRUMENTATION = 0x00000008;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting an activity.
+     */
+    static final int HOSTING_COMPONENT_TYPE_ACTIVITY = 0x00000010;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting a broadcast receiver.
+     */
+    static final int HOSTING_COMPONENT_TYPE_BROADCAST_RECEIVER = 0x00000020;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting a content provider.
+     */
+    static final int HOSTING_COMPONENT_TYPE_PROVIDER = 0x00000040;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting a started service.
+     */
+    static final int HOSTING_COMPONENT_TYPE_STARTED_SERVICE = 0x00000080;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's hosting a foreground service.
+     */
+    static final int HOSTING_COMPONENT_TYPE_FOREGROUND_SERVICE = 0x00000100;
+
+    /**
+     * The type of the component this process is hosting;
+     * this means it's being bound via a service binding.
+     */
+    static final int HOSTING_COMPONENT_TYPE_BOUND_SERVICE = 0x00000200;
+
+    @IntDef(flag = true, prefix = { "HOSTING_COMPONENT_TYPE_" }, value = {
+            HOSTING_COMPONENT_TYPE_EMPTY,
+            HOSTING_COMPONENT_TYPE_SYSTEM,
+            HOSTING_COMPONENT_TYPE_PERSISTENT,
+            HOSTING_COMPONENT_TYPE_BACKUP,
+            HOSTING_COMPONENT_TYPE_INSTRUMENTATION,
+            HOSTING_COMPONENT_TYPE_ACTIVITY,
+            HOSTING_COMPONENT_TYPE_BROADCAST_RECEIVER,
+            HOSTING_COMPONENT_TYPE_PROVIDER,
+            HOSTING_COMPONENT_TYPE_STARTED_SERVICE,
+            HOSTING_COMPONENT_TYPE_FOREGROUND_SERVICE,
+            HOSTING_COMPONENT_TYPE_BOUND_SERVICE,
+    })
+    @interface HostingComponentType {}
+
     final ProcessRecord mApp;
 
     private final ActivityManagerService mService;
@@ -194,6 +278,12 @@
     @GuardedBy("mProfilerLock")
     private long mLastStateTime;
 
+    private AtomicInteger mCurrentHostingComponentTypes =
+            new AtomicInteger(HOSTING_COMPONENT_TYPE_EMPTY);
+
+    private AtomicInteger mHistoricalHostingComponentTypes =
+            new AtomicInteger(HOSTING_COMPONENT_TYPE_EMPTY);
+
     private final ActivityManagerGlobalLock mProcLock;
 
     ProcessProfileRecord(final ProcessRecord app) {
@@ -292,6 +382,8 @@
                 mThread = null;
             }
         }
+        mCurrentHostingComponentTypes.set(HOSTING_COMPONENT_TYPE_EMPTY);
+        mHistoricalHostingComponentTypes.set(HOSTING_COMPONENT_TYPE_EMPTY);
     }
 
     @GuardedBy("mProfilerLock")
@@ -605,6 +697,23 @@
         mLastStateTime = state.getLastStateTime();
     }
 
+    void addHostingComponentType(@HostingComponentType int type) {
+        mCurrentHostingComponentTypes.set(mCurrentHostingComponentTypes.get() | type);
+        mHistoricalHostingComponentTypes.set(mHistoricalHostingComponentTypes.get() | type);
+    }
+
+    void clearHostingComponentType(@HostingComponentType int type) {
+        mCurrentHostingComponentTypes.set(mCurrentHostingComponentTypes.get() & ~type);
+    }
+
+    @HostingComponentType int getCurrentHostingComponentTypes() {
+        return mCurrentHostingComponentTypes.get();
+    }
+
+    @HostingComponentType int getHistoricalHostingComponentTypes() {
+        return mHistoricalHostingComponentTypes.get();
+    }
+
     @GuardedBy("mService")
     void dumpPss(PrintWriter pw, String prefix, long nowUptime) {
         synchronized (mProfilerLock) {
@@ -643,6 +752,11 @@
             pw.print(" reportLowMemory=");
             pw.println(mReportLowMemory);
         }
+        pw.print(prefix);
+        pw.print("currentHostingComponentTypes=0x");
+        pw.print(Integer.toHexString(getCurrentHostingComponentTypes()));
+        pw.print(" historicalHostingComponentTypes=0x");
+        pw.println(Integer.toHexString(getHistoricalHostingComponentTypes()));
     }
 
     void dumpCputime(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 6b748193..486c8ed 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -16,6 +16,9 @@
 
 package com.android.server.am;
 
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_FOREGROUND_SERVICE;
+
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.IBinder;
@@ -141,6 +144,11 @@
         mHasForegroundServices = hasForegroundServices;
         mFgServiceTypes = fgServiceTypes;
         mApp.getWindowProcessController().setHasForegroundServices(hasForegroundServices);
+        if (hasForegroundServices) {
+            mApp.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_FOREGROUND_SERVICE);
+        } else {
+            mApp.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_FOREGROUND_SERVICE);
+        }
     }
 
     boolean hasForegroundServices() {
@@ -295,6 +303,7 @@
         boolean added = mServices.add(record);
         if (added && record.serviceInfo != null) {
             mApp.getWindowProcessController().onServiceStarted(record.serviceInfo);
+            updateHostingComonentTypeForBindingsLocked();
         }
         if (record.lastTopAlmostPerceptibleBindRequestUptimeMs > 0) {
             mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = Math.max(
@@ -318,6 +327,9 @@
         if (record.lastTopAlmostPerceptibleBindRequestUptimeMs > 0) {
             updateHasTopStartedAlmostPerceptibleServices();
         }
+        if (removed) {
+            updateHostingComonentTypeForBindingsLocked();
+        }
         return removed;
     }
 
@@ -437,6 +449,23 @@
     }
 
     @GuardedBy("mService")
+    void updateHostingComonentTypeForBindingsLocked() {
+        boolean hasBoundClient = false;
+        for (int i = numberOfRunningServices() - 1; i >= 0; i--) {
+            final ServiceRecord sr = getRunningServiceAt(i);
+            if (sr != null && !sr.getConnections().isEmpty()) {
+                hasBoundClient = true;
+                break;
+            }
+        }
+        if (hasBoundClient) {
+            mApp.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_BOUND_SERVICE);
+        } else {
+            mApp.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_BOUND_SERVICE);
+        }
+    }
+
+    @GuardedBy("mService")
     boolean incServiceCrashCountLocked(long now) {
         final boolean procIsBoundForeground = mApp.mState.getCurProcState()
                 == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index e0660b4..262436d 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -21,6 +21,9 @@
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_ACTIVITY;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_BROADCAST_RECEIVER;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_STARTED_SERVICE;
 import static com.android.server.am.ProcessRecord.TAG;
 
 import android.annotation.ElapsedRealtimeLong;
@@ -694,6 +697,11 @@
     @GuardedBy("mProcLock")
     void setHasStartedServices(boolean hasStartedServices) {
         mHasStartedServices = hasStartedServices;
+        if (hasStartedServices) {
+            mApp.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_STARTED_SERVICE);
+        } else {
+            mApp.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_STARTED_SERVICE);
+        }
     }
 
     @GuardedBy("mProcLock")
@@ -999,6 +1007,11 @@
         if (mCachedHasActivities == VALUE_INVALID) {
             mCachedHasActivities = mApp.getWindowProcessController().hasActivities() ? VALUE_TRUE
                     : VALUE_FALSE;
+            if (mCachedHasActivities == VALUE_TRUE) {
+                mApp.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_ACTIVITY);
+            } else {
+                mApp.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_ACTIVITY);
+            }
         }
         return mCachedHasActivities == VALUE_TRUE;
     }
@@ -1065,6 +1078,9 @@
             if (mCachedIsReceivingBroadcast == VALUE_TRUE) {
                 mCachedSchedGroup = tmpQueue.contains(mService.mFgBroadcastQueue)
                         ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
+                mApp.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_BROADCAST_RECEIVER);
+            } else {
+                mApp.mProfile.clearHostingComponentType(HOSTING_COMPONENT_TYPE_BROADCAST_RECEIVER);
             }
         }
         return mCachedIsReceivingBroadcast == VALUE_TRUE;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 480e69b..4b82ad8 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -23,6 +23,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -693,6 +694,7 @@
                 app.removeAllowBackgroundActivityStartsToken(this);
             }
             app.mServices.updateBoundClientUids();
+            app.mServices.updateHostingComonentTypeForBindingsLocked();
         }
         app = proc;
         if (pendingConnectionGroup > 0 && proc != null) {
@@ -717,6 +719,7 @@
         }
         if (proc != null) {
             proc.mServices.updateBoundClientUids();
+            proc.mServices.updateHostingComonentTypeForBindingsLocked();
         }
     }
 
@@ -736,6 +739,7 @@
         // if we have a process attached, add bound client uid of this connection to it
         if (app != null) {
             app.mServices.addBoundClientUid(c.clientUid);
+            app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_BOUND_SERVICE);
         }
     }
 
@@ -744,6 +748,7 @@
         // if we have a process attached, tell it to update the state of bound clients
         if (app != null) {
             app.mServices.updateBoundClientUids();
+            app.mServices.updateHostingComonentTypeForBindingsLocked();
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/AppsFilterBase.java b/services/core/java/com/android/server/pm/AppsFilterBase.java
index 78e7b0a..7ca1978 100644
--- a/services/core/java/com/android/server/pm/AppsFilterBase.java
+++ b/services/core/java/com/android/server/pm/AppsFilterBase.java
@@ -321,6 +321,9 @@
                     || targetPkgSetting.getAppId() < Process.FIRST_APPLICATION_UID
                     || callingAppId == targetPkgSetting.getAppId()) {
                 return false;
+            } else if (Process.isSdkSandboxUid(callingAppId)) {
+                // we only allow sdk sandbox processes access to forcequeryable packages
+                return !isForceQueryable(targetPkgSetting.getAppId());
             }
             if (mCacheReady) { // use cache
                 if (!shouldFilterApplicationUsingCache(callingUid,
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index fa506ca..140ac33 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -76,6 +76,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Trace;
 import android.util.ArrayMap;
@@ -145,7 +146,8 @@
      * Returns the currently visible window that is associated with the wallpaper in case we are
      * transitioning from an activity with a wallpaper to one without.
      */
-    private @Nullable WindowState getOldWallpaper() {
+    @Nullable
+    private WindowState getOldWallpaper() {
         final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
         final @TransitionType int firstTransit =
                 mDisplayContent.mAppTransition.getFirstAppTransition();
@@ -165,6 +167,16 @@
                 ? null : wallpaperTarget;
     }
 
+    @NonNull
+    private static ArraySet<ActivityRecord> getAppsForAnimation(
+            @NonNull ArraySet<ActivityRecord> apps, boolean excludeLauncherFromAnimation) {
+        final ArraySet<ActivityRecord> appsForAnimation = new ArraySet<>(apps);
+        if (excludeLauncherFromAnimation) {
+            appsForAnimation.removeIf(ConfigurationContainer::isActivityTypeHome);
+        }
+        return appsForAnimation;
+    }
+
     /**
      * Handle application transition for given display.
      */
@@ -214,18 +226,29 @@
         mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(
                 mDisplayContent.mOpeningApps);
 
-        final @TransitionOldType int transit = getTransitCompatType(
-                mDisplayContent.mAppTransition, mDisplayContent.mOpeningApps,
-                mDisplayContent.mClosingApps, mDisplayContent.mChangingContainers,
+        // Remove launcher from app transition animation while recents is running. Recents animation
+        // is managed outside of app transition framework, so we just need to commit visibility.
+        final boolean excludeLauncherFromAnimation =
+                mDisplayContent.mOpeningApps.stream().anyMatch(
+                        (app) -> app.isAnimating(PARENTS, ANIMATION_TYPE_RECENTS))
+                || mDisplayContent.mClosingApps.stream().anyMatch(
+                        (app) -> app.isAnimating(PARENTS, ANIMATION_TYPE_RECENTS));
+        final ArraySet<ActivityRecord> openingAppsForAnimation = getAppsForAnimation(
+                mDisplayContent.mOpeningApps, excludeLauncherFromAnimation);
+        final ArraySet<ActivityRecord> closingAppsForAnimation = getAppsForAnimation(
+                mDisplayContent.mClosingApps, excludeLauncherFromAnimation);
+
+        @TransitionOldType final int transit = getTransitCompatType(
+                mDisplayContent.mAppTransition, openingAppsForAnimation, closingAppsForAnimation,
+                mDisplayContent.mChangingContainers,
                 mWallpaperControllerLocked.getWallpaperTarget(), getOldWallpaper(),
                 mDisplayContent.mSkipAppTransitionAnimation);
         mDisplayContent.mSkipAppTransitionAnimation = false;
 
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                 "handleAppTransitionReady: displayId=%d appTransition={%s}"
-                + " openingApps=[%s] closingApps=[%s] transit=%s",
-                mDisplayContent.mDisplayId,
-                appTransition.toString(),
+                + " excludeLauncherFromAnimation=%b openingApps=[%s] closingApps=[%s] transit=%s",
+                mDisplayContent.mDisplayId, appTransition.toString(), excludeLauncherFromAnimation,
                 mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
                 AppTransition.appTransitionOldToString(transit));
 
@@ -233,13 +256,15 @@
         // what will control the animation theme. If all closing windows are obscured, then there is
         // no need to do an animation. This is the case, for example, when this transition is being
         // done behind a dream window.
-        final ArraySet<Integer> activityTypes = collectActivityTypes(mDisplayContent.mOpeningApps,
-                mDisplayContent.mClosingApps, mDisplayContent.mChangingContainers);
-        final ActivityRecord animLpActivity = findAnimLayoutParamsToken(transit, activityTypes);
+        final ArraySet<Integer> activityTypes = collectActivityTypes(openingAppsForAnimation,
+                closingAppsForAnimation, mDisplayContent.mChangingContainers);
+        final ActivityRecord animLpActivity = findAnimLayoutParamsToken(transit, activityTypes,
+                openingAppsForAnimation, closingAppsForAnimation,
+                mDisplayContent.mChangingContainers);
         final ActivityRecord topOpeningApp =
-                getTopApp(mDisplayContent.mOpeningApps, false /* ignoreHidden */);
+                getTopApp(openingAppsForAnimation, false /* ignoreHidden */);
         final ActivityRecord topClosingApp =
-                getTopApp(mDisplayContent.mClosingApps, false /* ignoreHidden */);
+                getTopApp(closingAppsForAnimation, false /* ignoreHidden */);
         final ActivityRecord topChangingApp =
                 getTopApp(mDisplayContent.mChangingContainers, false /* ignoreHidden */);
         final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);
@@ -251,14 +276,14 @@
             overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
         }
 
-        final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mClosingApps)
-                || containsVoiceInteraction(mDisplayContent.mOpeningApps);
+        final boolean voiceInteraction = containsVoiceInteraction(closingAppsForAnimation)
+                || containsVoiceInteraction(openingAppsForAnimation);
 
         final int layoutRedo;
         mService.mSurfaceAnimationRunner.deferStartingAnimations();
         try {
-            applyAnimations(mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps, transit,
-                    animLp, voiceInteraction);
+            applyAnimations(openingAppsForAnimation, closingAppsForAnimation, transit, animLp,
+                    voiceInteraction);
             handleClosingApps();
             handleOpeningApps();
             handleChangingApps(transit);
@@ -310,7 +335,7 @@
      *                     case we are transitioning from an activity with a wallpaper to one
      *                     without. Otherwise null.
      */
-    static @TransitionOldType int getTransitCompatType(AppTransition appTransition,
+    @TransitionOldType static int getTransitCompatType(AppTransition appTransition,
             ArraySet<ActivityRecord> openingApps, ArraySet<ActivityRecord> closingApps,
             ArraySet<WindowContainer> changingContainers, @Nullable WindowState wallpaperTarget,
             @Nullable WindowState oldWallpaper, boolean skipAppTransitionAnimation) {
@@ -341,8 +366,8 @@
         if (skipAppTransitionAnimation) {
             return WindowManager.TRANSIT_OLD_UNSET;
         }
-        final @TransitionFlags int flags = appTransition.getTransitFlags();
-        final @TransitionType int firstTransit = appTransition.getFirstAppTransition();
+        @TransitionFlags final int flags = appTransition.getTransitFlags();
+        @TransitionType final int firstTransit = appTransition.getFirstAppTransition();
 
         // Special transitions
         // TODO(new-app-transitions): Revisit if those can be rewritten by using flags.
@@ -720,11 +745,9 @@
      */
     @Nullable
     private ActivityRecord findAnimLayoutParamsToken(@TransitionOldType int transit,
-            ArraySet<Integer> activityTypes) {
+            ArraySet<Integer> activityTypes, ArraySet<ActivityRecord> openingApps,
+            ArraySet<ActivityRecord> closingApps, ArraySet<WindowContainer> changingApps) {
         ActivityRecord result;
-        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
-        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
-        final ArraySet<WindowContainer> changingApps = mDisplayContent.mChangingContainers;
 
         // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
         result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
@@ -1152,11 +1175,6 @@
             if (activity == null) {
                 continue;
             }
-            if (activity.isAnimating(PARENTS, ANIMATION_TYPE_RECENTS)) {
-                ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                        "Delaying app transition for recents animation to finish");
-                return false;
-            }
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                     "Check opening app=%s: allDrawn=%b startingDisplayed=%b "
                             + "startingMoved=%b isRelaunching()=%b startingWindow=%s",
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
index 9674ebd..facbe80 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
@@ -1336,6 +1336,46 @@
 
     }
 
+    @Test
+    public void testSdkSandbox_canSeeForceQueryable() throws Exception {
+        final AppsFilterImpl appsFilter =
+                new AppsFilterImpl(mFeatureConfigMock, new String[]{}, false, null,
+                        mMockHandler);
+        simulateAddBasicAndroid(appsFilter);
+        appsFilter.onSystemReady(mPmInternal);
+
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_APPID,
+                setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
+
+        int callingUid = 20123;
+        assertTrue(Process.isSdkSandboxUid(callingUid));
+
+        assertFalse(
+                appsFilter.shouldFilterApplication(mSnapshot, callingUid,
+                        null /* callingSetting */, target, SYSTEM_USER));
+    }
+
+    @Test
+    public void testSdkSandbox_cannotSeeNonForceQueryable() throws Exception {
+        final AppsFilterImpl appsFilter =
+                new AppsFilterImpl(mFeatureConfigMock, new String[]{}, false, null,
+                        mMockHandler);
+        simulateAddBasicAndroid(appsFilter);
+        appsFilter.onSystemReady(mPmInternal);
+
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_APPID,
+                setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
+
+        int callingUid = 20123;
+        assertTrue(Process.isSdkSandboxUid(callingUid));
+
+        assertTrue(
+                appsFilter.shouldFilterApplication(mSnapshot, callingUid,
+                        null /* callingSetting */, target, SYSTEM_USER));
+    }
+
     private List<Integer> toList(int[] array) {
         ArrayList<Integer> ret = new ArrayList<>(array.length);
         for (int i = 0; i < array.length; i++) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 3592158..436cf36 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_CHANGE;
@@ -25,6 +27,7 @@
 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
@@ -409,38 +412,50 @@
     }
 
     @Test
-    public void testDelayWhileRecents() {
+    public void testExcludeLauncher() {
         final DisplayContent dc = createNewDisplay(Display.STATE_ON);
         doReturn(false).when(dc).onDescendantOrientationChanged(any());
         final Task task = createTask(dc);
 
-        // Simulate activity1 launches activity2.
+        // Simulate activity1 launches activity2
         final ActivityRecord activity1 = createActivityRecord(task);
         activity1.setVisible(true);
         activity1.mVisibleRequested = false;
         activity1.allDrawn = true;
+        dc.mClosingApps.add(activity1);
         final ActivityRecord activity2 = createActivityRecord(task);
         activity2.setVisible(false);
         activity2.mVisibleRequested = true;
         activity2.allDrawn = true;
-
-        dc.mClosingApps.add(activity1);
         dc.mOpeningApps.add(activity2);
         dc.prepareAppTransition(TRANSIT_OPEN);
-        assertTrue(dc.mAppTransition.containsTransitRequest(TRANSIT_OPEN));
+
+        // Simulate start recents
+        final ActivityRecord homeActivity = createActivityRecord(dc, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_HOME);
+        homeActivity.setVisible(false);
+        homeActivity.mVisibleRequested = true;
+        homeActivity.allDrawn = true;
+        dc.mOpeningApps.add(homeActivity);
+        dc.prepareAppTransition(TRANSIT_NONE);
+        doReturn(true).when(task)
+                .isSelfAnimating(anyInt(), eq(ANIMATION_TYPE_RECENTS));
 
         // Wait until everything in animation handler get executed to prevent the exiting window
         // from being removed during WindowSurfacePlacer Traversal.
         waitUntilHandlersIdle();
 
-        // Start recents
-        doReturn(true).when(task)
-                .isSelfAnimating(anyInt(), eq(ANIMATION_TYPE_RECENTS));
-
         dc.mAppTransitionController.handleAppTransitionReady();
 
-        verify(activity1, never()).commitVisibility(anyBoolean(), anyBoolean(), anyBoolean());
-        verify(activity2, never()).commitVisibility(anyBoolean(), anyBoolean(), anyBoolean());
+        verify(activity1).commitVisibility(eq(false), anyBoolean(), anyBoolean());
+        verify(activity1).applyAnimation(any(), eq(TRANSIT_OLD_ACTIVITY_OPEN), eq(false),
+                anyBoolean(), any());
+        verify(activity2).commitVisibility(eq(true), anyBoolean(), anyBoolean());
+        verify(activity2).applyAnimation(any(), eq(TRANSIT_OLD_ACTIVITY_OPEN), eq(true),
+                anyBoolean(), any());
+        verify(homeActivity).commitVisibility(eq(true), anyBoolean(), anyBoolean());
+        verify(homeActivity, never()).applyAnimation(any(), anyInt(), anyBoolean(), anyBoolean(),
+                any());
     }
 
     @Test