Merge "Add the AVRCP Target Service (2/2)" into pi-dev
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 7a55f60..ef637df 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -92,6 +92,10 @@
 const int FIELD_ID_UID_MAP_DROPPED_SNAPSHOTS = 4;
 const int FIELD_ID_UID_MAP_DROPPED_CHANGES = 5;
 
+const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = {
+        {android::util::CPU_TIME_PER_UID_FREQ, {6000, 10000}},
+};
+
 // TODO: add stats for pulled atoms.
 StatsdStats::StatsdStats() {
     mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index a4f64dd..7675888 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -81,6 +81,9 @@
     const static int kDimensionKeySizeSoftLimit = 300;
     const static int kDimensionKeySizeHardLimit = 500;
 
+    // Per atom dimension key size limit
+    static const std::map<int, std::pair<size_t, size_t>> kAtomDimensionKeySizeLimitMap;
+
     const static int kMaxConfigCount = 10;
     const static int kMaxAlertCountPerConfig = 100;
     const static int kMaxConditionCountPerConfig = 200;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 49034ac..f08d54a 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -17,9 +17,9 @@
 #define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
+#include "../guardrail/StatsdStats.h"
 #include "GaugeMetricProducer.h"
-#include "guardrail/StatsdStats.h"
-#include "stats_log_util.h"
+#include "../stats_log_util.h"
 
 #include <cutils/log.h>
 
@@ -60,12 +60,20 @@
 
 GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
                                          const int conditionIndex,
-                                         const sp<ConditionWizard>& wizard,
-                                         const int pullTagId, const uint64_t startTimeNs,
+                                         const sp<ConditionWizard>& wizard, const int pullTagId,
+                                         const uint64_t startTimeNs,
                                          shared_ptr<StatsPullerManager> statsPullerManager)
     : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
       mStatsPullerManager(statsPullerManager),
-      mPullTagId(pullTagId) {
+      mPullTagId(pullTagId),
+      mDimensionSoftLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
+                                          StatsdStats::kAtomDimensionKeySizeLimitMap.end()
+                                  ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).first
+                                  : StatsdStats::kDimensionKeySizeSoftLimit),
+      mDimensionHardLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
+                                          StatsdStats::kAtomDimensionKeySizeLimitMap.end()
+                                  ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).second
+                                  : StatsdStats::kDimensionKeySizeHardLimit) {
     mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
     mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
     int64_t bucketSizeMills = 0;
@@ -305,11 +313,11 @@
         return false;
     }
     // 1. Report the tuple count if the tuple count > soft limit
-    if (mCurrentSlicedBucket->size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
+    if (mCurrentSlicedBucket->size() > mDimensionSoftLimit - 1) {
         size_t newTupleCount = mCurrentSlicedBucket->size() + 1;
         StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
         // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
-        if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
+        if (newTupleCount > mDimensionHardLimit) {
             ALOGE("GaugeMetric %lld dropping data for dimension key %s",
                 (long long)mMetricId, newKey.toString().c_str());
             return true;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index dd6aff4..4b543f8 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -150,6 +150,10 @@
 
     static const size_t kBucketSize = sizeof(GaugeBucket{});
 
+    const size_t mDimensionSoftLimit;
+
+    const size_t mDimensionHardLimit;
+
     FRIEND_TEST(GaugeMetricProducerTest, TestWithCondition);
     FRIEND_TEST(GaugeMetricProducerTest, TestNoCondition);
     FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 767260d..ed4d7e4 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -18,8 +18,8 @@
 #include "Log.h"
 
 #include "ValueMetricProducer.h"
-#include "guardrail/StatsdStats.h"
-#include "stats_log_util.h"
+#include "../guardrail/StatsdStats.h"
+#include "../stats_log_util.h"
 
 #include <cutils/log.h>
 #include <limits.h>
@@ -68,7 +68,15 @@
     : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
       mValueField(metric.value_field()),
       mStatsPullerManager(statsPullerManager),
-      mPullTagId(pullTagId) {
+      mPullTagId(pullTagId),
+      mDimensionSoftLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
+                                          StatsdStats::kAtomDimensionKeySizeLimitMap.end()
+                                  ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).first
+                                  : StatsdStats::kDimensionKeySizeSoftLimit),
+      mDimensionHardLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
+                                          StatsdStats::kAtomDimensionKeySizeLimitMap.end()
+                                  ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).second
+                                  : StatsdStats::kDimensionKeySizeHardLimit) {
     // TODO: valuemetric for pushed events may need unlimited bucket length
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
@@ -266,11 +274,11 @@
     if (mCurrentSlicedBucket.find(newKey) != mCurrentSlicedBucket.end()) {
         return false;
     }
-    if (mCurrentSlicedBucket.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
+    if (mCurrentSlicedBucket.size() > mDimensionSoftLimit - 1) {
         size_t newTupleCount = mCurrentSlicedBucket.size() + 1;
         StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
         // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
-        if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
+        if (newTupleCount > mDimensionHardLimit) {
             ALOGE("ValueMetric %lld dropping data for dimension key %s",
                 (long long)mMetricId, newKey.toString().c_str());
             return true;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index be57183..c4477b3 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -149,6 +149,10 @@
 
     static const size_t kBucketSize = sizeof(ValueBucket{});
 
+    const size_t mDimensionSoftLimit;
+
+    const size_t mDimensionHardLimit;
+
     FRIEND_TEST(ValueMetricProducerTest, TestNonDimensionalEvents);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade);
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 31ed549..f332358 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.os.Build;
 import android.text.Layout;
 import android.text.NoCopySpan;
 import android.text.Selection;
@@ -35,6 +36,8 @@
     private static final int UP = 2;
     private static final int DOWN = 3;
 
+    private static final int HIDE_FLOATING_TOOLBAR_DELAY_MS = 200;
+
     @Override
     public boolean canSelectArbitrarily() {
         return true;
@@ -65,7 +68,7 @@
 
         return super.up(widget, buffer);
     }
-        
+
     @Override
     protected boolean down(TextView widget, Spannable buffer) {
         if (action(DOWN, widget, buffer)) {
@@ -215,6 +218,12 @@
                 if (action == MotionEvent.ACTION_UP) {
                     links[0].onClick(widget);
                 } else if (action == MotionEvent.ACTION_DOWN) {
+                    if (widget.getContext().getApplicationInfo().targetSdkVersion
+                            > Build.VERSION_CODES.O_MR1) {
+                        // Selection change will reposition the toolbar. Hide it for a few ms for a
+                        // smoother transition.
+                        widget.hideFloatingToolbar(HIDE_FLOATING_TOOLBAR_DELAY_MS);
+                    }
                     Selection.setSelection(buffer,
                         buffer.getSpanStart(links[0]),
                         buffer.getSpanEnd(links[0]));
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 92285c7..3775835 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -289,6 +289,7 @@
     boolean mShowSoftInputOnFocus = true;
     private boolean mPreserveSelection;
     private boolean mRestartActionModeOnNextRefresh;
+    private boolean mRequestingLinkActionMode;
 
     private SelectionActionModeHelper mSelectionActionModeHelper;
 
@@ -2127,6 +2128,7 @@
             return;
         }
         stopTextActionMode();
+        mRequestingLinkActionMode = true;
         getSelectionActionModeHelper().startLinkActionModeAsync(start, end);
     }
 
@@ -2212,7 +2214,9 @@
         mTextActionMode = mTextView.startActionMode(actionModeCallback, ActionMode.TYPE_FLOATING);
 
         final boolean selectionStarted = mTextActionMode != null;
-        if (selectionStarted && !mTextView.isTextSelectable() && mShowSoftInputOnFocus) {
+        if (selectionStarted
+                && mTextView.isTextEditable() && !mTextView.isTextSelectable()
+                && mShowSoftInputOnFocus) {
             // Show the IME to be able to replace text, except when selecting non editable text.
             final InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) {
@@ -2322,10 +2326,14 @@
         if (!selectAllGotFocus && text.length() > 0) {
             // Move cursor
             final int offset = mTextView.getOffsetForPosition(event.getX(), event.getY());
-            Selection.setSelection((Spannable) text, offset);
-            if (mSpellChecker != null) {
-                // When the cursor moves, the word that was typed may need spell check
-                mSpellChecker.onSelectionChanged();
+
+            final boolean shouldInsertCursor = !mRequestingLinkActionMode;
+            if (shouldInsertCursor) {
+                Selection.setSelection((Spannable) text, offset);
+                if (mSpellChecker != null) {
+                    // When the cursor moves, the word that was typed may need spell check
+                    mSpellChecker.onSelectionChanged();
+                }
             }
 
             if (!extractedTextModeWillBeStarted()) {
@@ -2335,16 +2343,17 @@
                         mTextView.removeCallbacks(mInsertionActionModeRunnable);
                     }
 
-                    mShowSuggestionRunnable = new Runnable() {
-                        public void run() {
-                            replace();
-                        }
-                    };
+                    mShowSuggestionRunnable = this::replace;
+
                     // removeCallbacks is performed on every touch
                     mTextView.postDelayed(mShowSuggestionRunnable,
                             ViewConfiguration.getDoubleTapTimeout());
                 } else if (hasInsertionController()) {
-                    getInsertionController().show();
+                    if (shouldInsertCursor) {
+                        getInsertionController().show();
+                    } else {
+                        getInsertionController().hide();
+                    }
                 }
             }
         }
@@ -4170,6 +4179,7 @@
             }
 
             mAssistClickHandlers.clear();
+            mRequestingLinkActionMode = false;
         }
 
         @Override
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 6e855ba..05204d0 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -71,7 +71,7 @@
     private final TextClassificationHelper mTextClassificationHelper;
     private final TextClassificationConstants mTextClassificationSettings;
 
-    private TextClassification mTextClassification;
+    @Nullable private TextClassification mTextClassification;
     private AsyncTask mTextClassificationAsyncTask;
 
     private final SelectionTracker mSelectionTracker;
@@ -124,7 +124,8 @@
                             : mTextClassificationHelper::classifyText,
                     mSmartSelectSprite != null
                             ? this::startSelectionActionModeWithSmartSelectAnimation
-                            : this::startSelectionActionMode)
+                            : this::startSelectionActionMode,
+                    mTextClassificationHelper::getOriginalSelection)
                     .execute();
         }
     }
@@ -143,7 +144,8 @@
                     mTextView,
                     mTextClassificationHelper.getTimeoutDuration(),
                     mTextClassificationHelper::classifyText,
-                    this::startLinkActionMode)
+                    this::startLinkActionMode,
+                    mTextClassificationHelper::getOriginalSelection)
                     .execute();
         }
     }
@@ -158,7 +160,8 @@
                     mTextView,
                     mTextClassificationHelper.getTimeoutDuration(),
                     mTextClassificationHelper::classifyText,
-                    this::invalidateActionMode)
+                    this::invalidateActionMode,
+                    mTextClassificationHelper::getOriginalSelection)
                     .execute();
         }
     }
@@ -822,6 +825,7 @@
         private final int mTimeOutDuration;
         private final Supplier<SelectionResult> mSelectionResultSupplier;
         private final Consumer<SelectionResult> mSelectionResultCallback;
+        private final Supplier<SelectionResult> mTimeOutResultSupplier;
         private final TextView mTextView;
         private final String mOriginalText;
 
@@ -830,16 +834,19 @@
          * @param timeOut time in milliseconds to timeout the query if it has not completed
          * @param selectionResultSupplier fetches the selection results. Runs on a background thread
          * @param selectionResultCallback receives the selection results. Runs on the UiThread
+         * @param timeOutResultSupplier default result if the task times out
          */
         TextClassificationAsyncTask(
                 @NonNull TextView textView, int timeOut,
                 @NonNull Supplier<SelectionResult> selectionResultSupplier,
-                @NonNull Consumer<SelectionResult> selectionResultCallback) {
+                @NonNull Consumer<SelectionResult> selectionResultCallback,
+                @NonNull Supplier<SelectionResult> timeOutResultSupplier) {
             super(textView != null ? textView.getHandler() : null);
             mTextView = Preconditions.checkNotNull(textView);
             mTimeOutDuration = timeOut;
             mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier);
             mSelectionResultCallback = Preconditions.checkNotNull(selectionResultCallback);
+            mTimeOutResultSupplier = Preconditions.checkNotNull(timeOutResultSupplier);
             // Make a copy of the original text.
             mOriginalText = getText(mTextView).toString();
         }
@@ -863,7 +870,7 @@
 
         private void onTimeOut() {
             if (getStatus() == Status.RUNNING) {
-                onPostExecute(null);
+                onPostExecute(mTimeOutResultSupplier.get());
             }
             cancel(true);
         }
@@ -963,6 +970,10 @@
             return performClassification(selection);
         }
 
+        public SelectionResult getOriginalSelection() {
+            return new SelectionResult(mSelectionStart, mSelectionEnd, null, null);
+        }
+
         /**
          * Maximum time (in milliseconds) to wait for a textclassifier result before timing out.
          */
@@ -1025,14 +1036,14 @@
     private static final class SelectionResult {
         private final int mStart;
         private final int mEnd;
-        private final TextClassification mClassification;
+        @Nullable private final TextClassification mClassification;
         @Nullable private final TextSelection mSelection;
 
         SelectionResult(int start, int end,
-                TextClassification classification, @Nullable TextSelection selection) {
+                @Nullable TextClassification classification, @Nullable TextSelection selection) {
             mStart = start;
             mEnd = end;
-            mClassification = Preconditions.checkNotNull(classification);
+            mClassification = classification;
             mSelection = selection;
         }
     }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index c366a91..7cf3e10 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11593,6 +11593,13 @@
         }
     }
 
+    /** @hide */
+    public void hideFloatingToolbar(int durationMs) {
+        if (mEditor != null) {
+            mEditor.hideFloatingToolbar(durationMs);
+        }
+    }
+
     boolean canUndo() {
         return mEditor != null && mEditor.canUndo();
     }
@@ -11687,7 +11694,7 @@
     boolean selectAllText() {
         if (mEditor != null) {
             // Hide the toolbar before changing the selection to avoid flickering.
-            mEditor.hideFloatingToolbar(FLOATING_TOOLBAR_SELECT_ALL_REFRESH_DELAY);
+            hideFloatingToolbar(FLOATING_TOOLBAR_SELECT_ALL_REFRESH_DELAY);
         }
         final int length = mText.length();
         Selection.setSelection((Spannable) mText, 0, length);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 6047f8e..a51cd93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -303,16 +303,18 @@
 
     @Override
     public void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        final int width = right - left;
-        final int height = bottom - top;
+        final int width = (right - left) - mNavigationBarView.getPaddingEnd()
+                - mNavigationBarView.getPaddingStart();
+        final int height = (bottom - top) - mNavigationBarView.getPaddingBottom()
+                - mNavigationBarView.getPaddingTop();
         final int x1, x2, y1, y2;
         if (mIsVertical) {
-            x1 = (width - mTrackThickness) / 2;
+            x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingStart();
             x2 = x1 + mTrackThickness;
             y1 = mDragPositive ? height / 2 : mTrackPadding;
             y2 = y1 + height / 2 - mTrackPadding;
         } else {
-            y1 = (height - mTrackThickness) / 2;
+            y1 = (height - mTrackThickness) / 2 + mNavigationBarView.getPaddingTop();
             y2 = y1 + mTrackThickness;
             x1 = mDragPositive ? width / 2 : mTrackPadding;
             x2 = x1 + width / 2 - mTrackPadding;
diff --git a/services/core/java/com/android/server/PruneInstantAppsJobService.java b/services/core/java/com/android/server/PruneInstantAppsJobService.java
index a6c3685..48e3a43 100644
--- a/services/core/java/com/android/server/PruneInstantAppsJobService.java
+++ b/services/core/java/com/android/server/PruneInstantAppsJobService.java
@@ -23,6 +23,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManagerInternal;
+import android.os.AsyncTask;
 
 import java.util.concurrent.TimeUnit;
 
@@ -47,10 +48,12 @@
 
     @Override
     public boolean onStartJob(JobParameters params) {
-        PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
-        packageManagerInternal.pruneInstantApps();
-        jobFinished(params, false);
+        AsyncTask.execute(() -> {
+            PackageManagerInternal packageManagerInternal = LocalServices.getService(
+                    PackageManagerInternal.class);
+            packageManagerInternal.pruneInstantApps();
+            jobFinished(params, false);
+        });
         return true;
     }
 
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 1335ced..efd81538 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -1243,15 +1243,13 @@
      */
     private int findRemoveIndexForAddTask(TaskRecord task) {
         final int recentsCount = mTasks.size();
-        final int taskActivityType = task.getActivityType();
         final Intent intent = task.intent;
         final boolean document = intent != null && intent.isDocument();
         int maxRecents = task.maxRecents - 1;
         for (int i = 0; i < recentsCount; i++) {
             final TaskRecord tr = mTasks.get(i);
-            final int trActivityType = tr.getActivityType();
             if (task != tr) {
-                if (taskActivityType != trActivityType || task.userId != tr.userId) {
+                if (!task.hasCompatibleActivityType(tr)) {
                     continue;
                 }
                 final Intent trIntent = tr.intent;
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 376f5b1..7765387 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -42,11 +42,13 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.RecentTaskInfo;
 import android.app.ActivityManager.RunningTaskInfo;
+import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Debug;
@@ -101,8 +103,8 @@
     private TestRecentTasks mRecentTasks;
     private TestRunningTasks mRunningTasks;
 
-    private static ArrayList<TaskRecord> mTasks = new ArrayList<>();
-    private static ArrayList<TaskRecord> mSameDocumentTasks = new ArrayList<>();
+    private ArrayList<TaskRecord> mTasks;
+    private ArrayList<TaskRecord> mSameDocumentTasks;
 
     private CallbacksRecorder mCallbacksRecorder;
 
@@ -155,12 +157,14 @@
         mRecentTasks.registerCallback(mCallbacksRecorder);
         QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
 
+        mTasks = new ArrayList<>();
         mTasks.add(createTaskBuilder(".Task1").build());
         mTasks.add(createTaskBuilder(".Task2").build());
         mTasks.add(createTaskBuilder(".Task3").build());
         mTasks.add(createTaskBuilder(".Task4").build());
         mTasks.add(createTaskBuilder(".Task5").build());
 
+        mSameDocumentTasks = new ArrayList<>();
         mSameDocumentTasks.add(createDocumentTask(".DocumentTask1"));
         mSameDocumentTasks.add(createDocumentTask(".DocumentTask1"));
     }
@@ -294,7 +298,32 @@
         assertTrue(mCallbacksRecorder.added.contains(task2));
         assertTrue(mCallbacksRecorder.trimmed.isEmpty());
         assertTrue(mCallbacksRecorder.removed.isEmpty());
+    }
 
+    @Test
+    public void testAddTaskCompatibleActivityType_expectRemove() throws Exception {
+        Configuration config1 = new Configuration();
+        config1.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+        TaskRecord task1 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK)
+                .setStack(mStack)
+                .build();
+        task1.onConfigurationChanged(config1);
+        assertTrue(task1.getActivityType() == ACTIVITY_TYPE_UNDEFINED);
+        mRecentTasks.add(task1);
+        mCallbacksRecorder.clear();
+
+        TaskRecord task2 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK)
+                .setStack(mStack)
+                .build();
+        assertTrue(task2.getActivityType() == ACTIVITY_TYPE_STANDARD);
+        mRecentTasks.add(task2);
+        assertTrue(mCallbacksRecorder.added.size() == 1);
+        assertTrue(mCallbacksRecorder.added.contains(task2));
+        assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+        assertTrue(mCallbacksRecorder.removed.size() == 1);
+        assertTrue(mCallbacksRecorder.removed.contains(task1));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
index ea207f1..9e6055d 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
@@ -29,6 +29,9 @@
 import java.io.File;
 import java.util.Random;
 
+/**
+ * atest FrameworksServicesTests:TaskPersisterTest
+ */
 public class TaskPersisterTest extends AndroidTestCase {
     private static final String TEST_USER_NAME = "AM-Test-User";
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c5386ef..a12a7a0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -40,6 +40,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.PersistableBundle;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -214,6 +215,10 @@
         return ActivityThread.currentOpPackageName();
     }
 
+    private boolean isSystemProcess() {
+        return Process.myUid() == Process.SYSTEM_UID;
+    }
+
     /**
      * Returns the multi SIM variant
      * Returns DSDS for Dual SIM Dual Standby
@@ -2866,15 +2871,18 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null) {
                 Rlog.e(TAG, "IMSI error: Subscriber Info is null");
+                if (!isSystemProcess()) {
+                    throw new RuntimeException("IMSI error: Subscriber Info is null");
+                }
                 return;
             }
             int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
             info.resetCarrierKeysForImsiEncryption(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException" + ex);
-        } catch (NullPointerException ex) {
-            // This could happen before phone restarts due to crashing
-            Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException" + ex);
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
         }
     }
 
@@ -3863,11 +3871,18 @@
     public void sendDialerSpecialCode(String inputCode) {
         try {
             final ITelephony telephony = getITelephony();
+            if (telephony == null) {
+                if (!isSystemProcess()) {
+                    throw new RuntimeException("Telephony service unavailable");
+                }
+                return;
+            }
             telephony.sendDialerSpecialCode(mContext.getOpPackageName(), inputCode);
         } catch (RemoteException ex) {
             // This could happen if binder process crashes.
-        } catch (NullPointerException ex) {
-            // This could happen before phone restarts due to crashing
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
         }
     }
 
@@ -7836,6 +7851,9 @@
             }
         } catch (RemoteException ex) {
             // This could happen if binder process crashes.
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
         }
     }
 }