diff options
60 files changed, 2902 insertions, 2012 deletions
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index bbaa20f232a9..001ad36134e9 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -107,6 +107,12 @@ DurationMetricProducer::DurationMetricProducer( ALOGE("Position ANY in dimension_in_what not supported."); } + // Dimensions in what must be subset of internal dimensions + if (!subsetDimensions(mDimensionsInWhat, mInternalDimensions)) { + ALOGE("Dimensions in what must be a subset of the internal dimensions"); + mValid = false; + } + mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()); if (metric.links().size() > 0) { @@ -115,6 +121,10 @@ DurationMetricProducer::DurationMetricProducer( mc.conditionId = link.condition(); translateFieldMatcher(link.fields_in_what(), &mc.metricFields); translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields); + if (!subsetDimensions(mc.metricFields, mInternalDimensions)) { + ALOGE(("Condition links must be a subset of the internal dimensions")); + mValid = false; + } mMetric2ConditionLinks.push_back(mc); } mConditionSliced = true; @@ -126,6 +136,10 @@ DurationMetricProducer::DurationMetricProducer( ms.stateAtomId = stateLink.state_atom_id(); translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields); translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields); + if (!subsetDimensions(ms.metricFields, mInternalDimensions)) { + ALOGE(("State links must be a subset of the dimensions in what internal dimensions")); + mValid = false; + } mMetric2StateLinks.push_back(ms); } diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index 5b321a0e3d60..c68e61e78f2e 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -56,6 +56,7 @@ MetricProducer::MetricProducer( : mMetricId(metricId), mProtoHash(protoHash), mConfigKey(key), + mValid(true), mTimeBaseNs(timeBaseNs), mCurrentBucketStartTimeNs(timeBaseNs), mCurrentBucketNum(0), diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 0dc8edae8056..7a1c008bd134 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -336,6 +336,10 @@ public: return mSlicedStateAtoms; } + inline bool isValid() const { + return mValid; + } + /* Adds an AnomalyTracker and returns it. */ virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) { @@ -468,6 +472,8 @@ protected: const ConfigKey mConfigKey; + bool mValid; + // The time when this metric producer was first created. The end time for the current bucket // can be computed from this based on mCurrentBucketNum. int64_t mTimeBaseNs; diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp index ff7938cc7243..bfa409cb8a64 100644 --- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp @@ -519,6 +519,7 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata( translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat); for (const auto& stateLink : metric.state_link()) { if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) { + ALOGW("DurationMetric's MetricStateLinks must be a subset of dimensions in what"); return nullopt; } } @@ -537,11 +538,15 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata( return nullopt; } - return {new DurationMetricProducer(key, metric, conditionIndex, initialConditionCache, - whatIndex, startIndex, stopIndex, stopAllIndex, nesting, - wizard, metricHash, internalDimensions, timeBaseNs, - currentTimeNs, eventActivationMap, eventDeactivationMap, - slicedStateAtoms, stateGroupMap)}; + sp<MetricProducer> producer = new DurationMetricProducer( + key, metric, conditionIndex, initialConditionCache, whatIndex, startIndex, stopIndex, + stopAllIndex, nesting, wizard, metricHash, internalDimensions, timeBaseNs, + currentTimeNs, eventActivationMap, eventDeactivationMap, slicedStateAtoms, + stateGroupMap); + if (!producer->isValid()) { + return nullopt; + } + return {producer}; } optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata( @@ -679,6 +684,7 @@ optional<sp<MetricProducer>> createValueMetricProducerAndUpdateMetadata( translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat); for (const auto& stateLink : metric.state_link()) { if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) { + ALOGW("ValueMetric's MetricStateLinks must be a subset of the dimensions in what"); return nullopt; } } diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp index 4efb038e538d..2473c1ca1101 100644 --- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp @@ -486,11 +486,11 @@ TEST(DurationMetricE2eTest, TestWithSlicedCondition) { // Links between wakelock state atom and condition of app is in background. auto links = durationMetric->add_links(); links->set_condition(isInBackgroundPredicate.id()); - auto dimensionWhat = links->mutable_fields_in_what(); - dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED); - dimensionWhat->add_child()->set_field(1); // uid field. - *links->mutable_fields_in_condition() = CreateAttributionUidDimensions( - util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST}); + *links->mutable_fields_in_what() = + CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + auto dimensionCondition = links->mutable_fields_in_condition(); + dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED); + dimensionCondition->add_child()->set_field(1); // uid field. ConfigKey cfgKey; uint64_t bucketStartTimeNs = 10000000000; @@ -591,11 +591,11 @@ TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) { // Links between wakelock state atom and condition of app is in background. auto links = durationMetric->add_links(); links->set_condition(isInBackgroundPredicate.id()); - auto dimensionWhat = links->mutable_fields_in_what(); - dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED); - dimensionWhat->add_child()->set_field(1); // uid field. - *links->mutable_fields_in_condition() = CreateAttributionUidDimensions( - util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST}); + *links->mutable_fields_in_what() = + CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + auto dimensionCondition = links->mutable_fields_in_condition(); + dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED); + dimensionCondition->add_child()->set_field(1); // uid field. auto metric_activation1 = config.add_metric_activation(); metric_activation1->set_metric_id(durationMetric->id()); @@ -1228,6 +1228,9 @@ TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset) { *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher(); auto holdingWakelockPredicate = CreateHoldingWakelockPredicate(); + *(holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions()) = + CreateAttributionUidAndOtherDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}, + {3 /* tag */}); *config.add_predicate() = holdingWakelockPredicate; auto uidProcessState = CreateUidProcessState(); diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp index 88df2ff0caa8..9ab7e47dce43 100644 --- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp +++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp @@ -882,6 +882,43 @@ TEST(MetricsManagerTest, TestCreateAnomalyTrackerDurationTooLong) { EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt); } +TEST(MetricsManagerTest, TestCreateDurationProducerDimensionsInWhatInvalid) { + StatsdConfig config; + config.add_allowed_log_source("AID_ROOT"); + *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher(); + *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher(); + *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); + *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher(); + + Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate(); + // The predicate is dimensioning by first attribution node by uid. + FieldMatcher dimensions = + CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions; + *config.add_predicate() = holdingWakelockPredicate; + + DurationMetric* durationMetric = config.add_duration_metric(); + durationMetric->set_id(StringToId("WakelockDuration")); + durationMetric->set_what(holdingWakelockPredicate.id()); + durationMetric->set_aggregation_type(DurationMetric::SUM); + // The metric is dimensioning by first attribution node by uid AND tag. + // Invalid since the predicate only dimensions by uid. + *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidAndOtherDimensions( + util::WAKELOCK_STATE_CHANGED, {Position::FIRST}, {3 /* tag */}); + durationMetric->set_bucket(FIVE_MINUTES); + + ConfigKey key(123, 987); + uint64_t timeNs = 456; + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + sp<UidMap> uidMap; + sp<MetricsManager> metricsManager = + new MetricsManager(key, config, timeNs, timeNs, uidMap, pullerManager, + anomalyAlarmMonitor, periodicAlarmMonitor); + EXPECT_FALSE(metricsManager->isConfigValid()); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 5ee5597e1984..f92768a28db1 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -963,8 +963,8 @@ public class Activity extends ContextThemeWrapper * @hide */ @Override - public void toggleFreeformWindowingMode() throws RemoteException { - ActivityTaskManager.getService().toggleFreeformWindowingMode(mToken); + public void toggleFreeformWindowingMode() { + ActivityClient.getInstance().toggleFreeformWindowingMode(mToken); } /** @@ -981,11 +981,8 @@ public class Activity extends ContextThemeWrapper @Override public boolean isTaskRoot() { - try { - return ActivityTaskManager.getService().getTaskForActivity(mToken, true) >= 0; - } catch (RemoteException e) { - return false; - } + return ActivityClient.getInstance().getTaskForActivity( + mToken, true /* onlyRoot */) >= 0; } /** @@ -2052,12 +2049,8 @@ public class Activity extends ContextThemeWrapper * {@link #isVoiceInteractionRoot()} return {@code false} in this case. */ public boolean isVoiceInteractionRoot() { - try { - return mVoiceInteractor != null - && ActivityTaskManager.getService().isRootVoiceInteraction(mToken); - } catch (RemoteException e) { - } - return false; + return mVoiceInteractor != null + && ActivityClient.getInstance().isRootVoiceInteraction(mToken); } /** @@ -2090,10 +2083,7 @@ public class Activity extends ContextThemeWrapper * @param privateOptions a Bundle of private arguments to the current voice interaction service */ public void startLocalVoiceInteraction(Bundle privateOptions) { - try { - ActivityTaskManager.getService().startLocalVoiceInteraction(mToken, privateOptions); - } catch (RemoteException re) { - } + ActivityClient.getInstance().startLocalVoiceInteraction(mToken, privateOptions); } /** @@ -2119,10 +2109,7 @@ public class Activity extends ContextThemeWrapper * terminated, {@link #onLocalVoiceInteractionStopped()} will be called. */ public void stopLocalVoiceInteraction() { - try { - ActivityTaskManager.getService().stopLocalVoiceInteraction(mToken); - } catch (RemoteException re) { - } + ActivityClient.getInstance().stopLocalVoiceInteraction(mToken); } /** @@ -2564,11 +2551,7 @@ public class Activity extends ContextThemeWrapper * false will be returned if the caller is not the current top activity. */ public boolean showAssist(Bundle args) { - try { - return ActivityTaskManager.getService().showAssistFromActivity(mToken, args); - } catch (RemoteException e) { - } - return false; + return ActivityClient.getInstance().showAssistFromActivity(mToken, args); } /** @@ -2708,10 +2691,9 @@ public class Activity extends ContextThemeWrapper } mDoReportFullyDrawn = false; try { - ActivityTaskManager.getService().reportActivityFullyDrawn( + ActivityClient.getInstance().reportActivityFullyDrawn( mToken, mRestoredFromBundle); VMRuntime.getRuntime().notifyStartupCompleted(); - } catch (RemoteException e) { } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } @@ -2841,27 +2823,23 @@ public class Activity extends ContextThemeWrapper * does not support picture-in-picture, return false. */ public boolean enterPictureInPictureMode(@NonNull PictureInPictureParams params) { - try { - if (!deviceSupportsPictureInPictureMode()) { - return false; - } - if (params == null) { - throw new IllegalArgumentException("Expected non-null picture-in-picture params"); - } - if (!mCanEnterPictureInPicture) { - throw new IllegalStateException("Activity must be resumed to enter" - + " picture-in-picture"); - } - // Set mIsInPictureInPictureMode earlier and don't wait for - // onPictureInPictureModeChanged callback here. This is to ensure that - // isInPictureInPictureMode returns true in the following onPause callback. - // See https://developer.android.com/guide/topics/ui/picture-in-picture for guidance. - mIsInPictureInPictureMode = ActivityTaskManager.getService().enterPictureInPictureMode( - mToken, params); - return mIsInPictureInPictureMode; - } catch (RemoteException e) { + if (!deviceSupportsPictureInPictureMode()) { return false; } + if (params == null) { + throw new IllegalArgumentException("Expected non-null picture-in-picture params"); + } + if (!mCanEnterPictureInPicture) { + throw new IllegalStateException("Activity must be resumed to enter" + + " picture-in-picture"); + } + // Set mIsInPictureInPictureMode earlier and don't wait for + // onPictureInPictureModeChanged callback here. This is to ensure that + // isInPictureInPictureMode returns true in the following onPause callback. + // See https://developer.android.com/guide/topics/ui/picture-in-picture for guidance. + mIsInPictureInPictureMode = ActivityClient.getInstance().enterPictureInPictureMode( + mToken, params); + return mIsInPictureInPictureMode; } /** @@ -2871,16 +2849,13 @@ public class Activity extends ContextThemeWrapper * @param params the new parameters for the picture-in-picture. */ public void setPictureInPictureParams(@NonNull PictureInPictureParams params) { - try { - if (!deviceSupportsPictureInPictureMode()) { - return; - } - if (params == null) { - throw new IllegalArgumentException("Expected non-null picture-in-picture params"); - } - ActivityTaskManager.getService().setPictureInPictureParams(mToken, params); - } catch (RemoteException e) { + if (!deviceSupportsPictureInPictureMode()) { + return; } + if (params == null) { + throw new IllegalArgumentException("Expected non-null picture-in-picture params"); + } + ActivityClient.getInstance().setPictureInPictureParams(mToken, params); } /** @@ -3822,14 +3797,10 @@ public class Activity extends ContextThemeWrapper finishAfterTransition(); return; } - try { - // Inform activity task manager that the activity received a back press - // while at the root of the task. This call allows ActivityTaskManager - // to intercept or move the task to the back. - ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken); - } catch (RemoteException e) { - finishAfterTransition(); - } + // Inform activity task manager that the activity received a back press while at the + // root of the task. This call allows ActivityTaskManager to intercept or move the task + // to the back. + ActivityClient.getInstance().onBackPressedOnTaskRoot(mToken); // Activity was launched when user tapped a link in the Autofill Save UI - Save UI must // be restored now. @@ -6114,11 +6085,8 @@ public class Activity extends ContextThemeWrapper * the outgoing activity. Use 0 for no animation. */ public void overridePendingTransition(int enterAnim, int exitAnim) { - try { - ActivityTaskManager.getService().overridePendingTransition( - mToken, getPackageName(), enterAnim, exitAnim); - } catch (RemoteException e) { - } + ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), + enterAnim, exitAnim); } /** @@ -6239,11 +6207,7 @@ public class Activity extends ContextThemeWrapper */ @Nullable public String getCallingPackage() { - try { - return ActivityTaskManager.getService().getCallingPackage(mToken); - } catch (RemoteException e) { - return null; - } + return ActivityClient.getInstance().getCallingPackage(mToken); } /** @@ -6262,11 +6226,7 @@ public class Activity extends ContextThemeWrapper */ @Nullable public ComponentName getCallingActivity() { - try { - return ActivityTaskManager.getService().getCallingActivity(mToken); - } catch (RemoteException e) { - return null; - } + return ActivityClient.getInstance().getCallingActivity(mToken); } /** @@ -6364,16 +6324,12 @@ public class Activity extends ContextThemeWrapper resultData = mResultData; } if (false) Log.v(TAG, "Finishing self: token=" + mToken); - try { - if (resultData != null) { - resultData.prepareToLeaveProcess(this); - } - if (ActivityTaskManager.getService() - .finishActivity(mToken, resultCode, resultData, finishTask)) { - mFinished = true; - } - } catch (RemoteException e) { - // Empty + if (resultData != null) { + resultData.prepareToLeaveProcess(this); + } + if (ActivityClient.getInstance().finishActivity(mToken, resultCode, resultData, + finishTask)) { + mFinished = true; } } else { mParent.finishFromChild(this); @@ -6429,12 +6385,8 @@ public class Activity extends ContextThemeWrapper if (mResultCode != RESULT_CANCELED || mResultData != null) { throw new IllegalStateException("Can not be called to deliver a result"); } - try { - if (ActivityTaskManager.getService().finishActivityAffinity(mToken)) { - mFinished = true; - } - } catch (RemoteException e) { - // Empty + if (ActivityClient.getInstance().finishActivityAffinity(mToken)) { + mFinished = true; } } @@ -6477,12 +6429,7 @@ public class Activity extends ContextThemeWrapper */ public void finishActivity(int requestCode) { if (mParent == null) { - try { - ActivityTaskManager.getService() - .finishSubActivity(mToken, mEmbeddedID, requestCode); - } catch (RemoteException e) { - // Empty - } + ActivityClient.getInstance().finishSubActivity(mToken, mEmbeddedID, requestCode); } else { mParent.finishActivityFromChild(this, requestCode); } @@ -6499,12 +6446,7 @@ public class Activity extends ContextThemeWrapper */ @Deprecated public void finishActivityFromChild(@NonNull Activity child, int requestCode) { - try { - ActivityTaskManager.getService() - .finishSubActivity(mToken, child.mEmbeddedID, requestCode); - } catch (RemoteException e) { - // Empty - } + ActivityClient.getInstance().finishSubActivity(mToken, child.mEmbeddedID, requestCode); } /** @@ -6527,12 +6469,7 @@ public class Activity extends ContextThemeWrapper * being finished, it hasn't yet saved its state, etc. */ public boolean releaseInstance() { - try { - return ActivityTaskManager.getService().releaseActivityInstance(mToken); - } catch (RemoteException e) { - // Empty - } - return false; + return ActivityClient.getInstance().releaseActivityInstance(mToken); } /** @@ -6644,12 +6581,7 @@ public class Activity extends ContextThemeWrapper */ public void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) { if (mParent == null) { - try { - ActivityTaskManager.getService().setRequestedOrientation( - mToken, requestedOrientation); - } catch (RemoteException e) { - // Empty - } + ActivityClient.getInstance().setRequestedOrientation(mToken, requestedOrientation); } else { mParent.setRequestedOrientation(requestedOrientation); } @@ -6667,16 +6599,10 @@ public class Activity extends ContextThemeWrapper @ActivityInfo.ScreenOrientation public int getRequestedOrientation() { if (mParent == null) { - try { - return ActivityTaskManager.getService() - .getRequestedOrientation(mToken); - } catch (RemoteException e) { - // Empty - } + return ActivityClient.getInstance().getRequestedOrientation(mToken); } else { return mParent.getRequestedOrientation(); } - return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; } /** @@ -6686,11 +6612,7 @@ public class Activity extends ContextThemeWrapper * @return Task identifier, an opaque integer. */ public int getTaskId() { - try { - return ActivityTaskManager.getService().getTaskForActivity(mToken, false); - } catch (RemoteException e) { - return -1; - } + return ActivityClient.getInstance().getTaskForActivity(mToken, false /* onlyRoot */); } /** @@ -6715,12 +6637,7 @@ public class Activity extends ContextThemeWrapper * back) true is returned, else false. */ public boolean moveTaskToBack(boolean nonRoot) { - try { - return ActivityTaskManager.getService().moveActivityTaskToBack(mToken, nonRoot); - } catch (RemoteException e) { - // Empty - } - return false; + return ActivityClient.getInstance().moveActivityTaskToBack(mToken, nonRoot); } /** @@ -6896,10 +6813,7 @@ public class Activity extends ContextThemeWrapper mTaskDescription.setIcon(Icon.createWithBitmap(icon)); } } - try { - ActivityTaskManager.getService().setTaskDescription(mToken, mTaskDescription); - } catch (RemoteException e) { - } + ActivityClient.getInstance().setTaskDescription(mToken, mTaskDescription); } /** @@ -7210,11 +7124,7 @@ public class Activity extends ContextThemeWrapper * @see android.content.pm.ActivityInfo#FLAG_IMMERSIVE */ public boolean isImmersive() { - try { - return ActivityTaskManager.getService().isImmersive(mToken); - } catch (RemoteException e) { - return false; - } + return ActivityClient.getInstance().isImmersive(mToken); } /** @@ -7228,11 +7138,7 @@ public class Activity extends ContextThemeWrapper if (mToken == null || mWindow == null) { return false; } - try { - return ActivityTaskManager.getService().isTopOfTask(getActivityToken()); - } catch (RemoteException e) { - return false; - } + return ActivityClient.getInstance().isTopOfTask(getActivityToken()); } /** @@ -7271,14 +7177,10 @@ public class Activity extends ContextThemeWrapper } private boolean convertFromTranslucentInternal() { - try { - mTranslucentCallback = null; - if (ActivityTaskManager.getService().convertFromTranslucent(mToken)) { - WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, true); - return true; - } - } catch (RemoteException e) { - // pass + mTranslucentCallback = null; + if (ActivityClient.getInstance().convertFromTranslucent(mToken)) { + WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, true /* opaque */); + return true; } return false; } @@ -7307,21 +7209,14 @@ public class Activity extends ContextThemeWrapper @SystemApi public boolean convertToTranslucent(TranslucentConversionListener callback, ActivityOptions options) { - boolean drawComplete; - try { - mTranslucentCallback = callback; - mChangeCanvasToTranslucent = ActivityTaskManager.getService().convertToTranslucent( - mToken, options == null ? null : options.toBundle()); - WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false); - drawComplete = true; - } catch (RemoteException e) { - // Make callback return as though it timed out. - mChangeCanvasToTranslucent = false; - drawComplete = false; - } + mTranslucentCallback = callback; + mChangeCanvasToTranslucent = ActivityClient.getInstance().convertToTranslucent( + mToken, options == null ? null : options.toBundle()); + WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false); + if (!mChangeCanvasToTranslucent && mTranslucentCallback != null) { // Window is already translucent. - mTranslucentCallback.onTranslucentConversionComplete(drawComplete); + mTranslucentCallback.onTranslucentConversionComplete(true /* drawComplete */); } return mChangeCanvasToTranslucent; } @@ -7355,12 +7250,7 @@ public class Activity extends ContextThemeWrapper */ @UnsupportedAppUsage ActivityOptions getActivityOptions() { - try { - return ActivityOptions.fromBundle( - ActivityTaskManager.getService().getActivityOptions(mToken)); - } catch (RemoteException e) { - } - return null; + return ActivityOptions.fromBundle(ActivityClient.getInstance().getActivityOptions(mToken)); } /** @@ -7504,11 +7394,7 @@ public class Activity extends ContextThemeWrapper * @see android.content.pm.ActivityInfo#FLAG_IMMERSIVE */ public void setImmersive(boolean i) { - try { - ActivityTaskManager.getService().setImmersive(mToken, i); - } catch (RemoteException e) { - // pass - } + ActivityClient.getInstance().setImmersive(mToken, i); } /** @@ -7567,14 +7453,8 @@ public class Activity extends ContextThemeWrapper */ public void setVrModeEnabled(boolean enabled, @NonNull ComponentName requestedComponent) throws PackageManager.NameNotFoundException { - try { - if (ActivityTaskManager.getService().setVrMode(mToken, enabled, requestedComponent) - != 0) { - throw new PackageManager.NameNotFoundException( - requestedComponent.flattenToString()); - } - } catch (RemoteException e) { - // pass + if (ActivityClient.getInstance().setVrMode(mToken, enabled, requestedComponent) != 0) { + throw new PackageManager.NameNotFoundException(requestedComponent.flattenToString()); } } @@ -7689,9 +7569,7 @@ public class Activity extends ContextThemeWrapper if (info.taskAffinity == null) { return false; } - return ActivityTaskManager.getService().shouldUpRecreateTask(mToken, info.taskAffinity); - } catch (RemoteException e) { - return false; + return ActivityClient.getInstance().shouldUpRecreateTask(mToken, info.taskAffinity); } catch (NameNotFoundException e) { return false; } @@ -7739,13 +7617,9 @@ public class Activity extends ContextThemeWrapper if (resultData != null) { resultData.prepareToLeaveProcess(this); } - try { - upIntent.prepareToLeaveProcess(this); - return ActivityTaskManager.getService().navigateUpTo(mToken, upIntent, - resultCode, resultData); - } catch (RemoteException e) { - return false; - } + upIntent.prepareToLeaveProcess(this); + return ActivityClient.getInstance().navigateUpTo(mToken, upIntent, resultCode, + resultData); } else { return mParent.navigateUpToFromChild(this, upIntent); } @@ -8361,10 +8235,7 @@ public class Activity extends ContextThemeWrapper * @see android.R.attr#lockTaskMode */ public void startLockTask() { - try { - ActivityTaskManager.getService().startLockTaskModeByToken(mToken); - } catch (RemoteException e) { - } + ActivityClient.getInstance().startLockTaskModeByToken(mToken); } /** @@ -8384,10 +8255,7 @@ public class Activity extends ContextThemeWrapper * @see ActivityManager#getLockTaskModeState() */ public void stopLockTask() { - try { - ActivityTaskManager.getService().stopLockTaskModeByToken(mToken); - } catch (RemoteException e) { - } + ActivityClient.getInstance().stopLockTaskModeByToken(mToken); } /** @@ -8396,10 +8264,7 @@ public class Activity extends ContextThemeWrapper * of this call for the message to be displayed. */ public void showLockTaskEscapeMessage() { - try { - ActivityTaskManager.getService().showLockTaskEscapeMessage(mToken); - } catch (RemoteException e) { - } + ActivityClient.getInstance().showLockTaskEscapeMessage(mToken); } /** @@ -8667,11 +8532,7 @@ public class Activity extends ContextThemeWrapper */ @UnsupportedAppUsage public void setDisablePreviewScreenshots(boolean disable) { - try { - ActivityTaskManager.getService().setDisablePreviewScreenshots(mToken, disable); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + ActivityClient.getInstance().setDisablePreviewScreenshots(mToken, disable); } /** @@ -8688,11 +8549,7 @@ public class Activity extends ContextThemeWrapper * @see android.R.attr#showWhenLocked */ public void setShowWhenLocked(boolean showWhenLocked) { - try { - ActivityTaskManager.getService().setShowWhenLocked(mToken, showWhenLocked); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + ActivityClient.getInstance().setShowWhenLocked(mToken, showWhenLocked); } /** @@ -8711,12 +8568,7 @@ public class Activity extends ContextThemeWrapper * @see android.R.attr#inheritShowWhenLocked */ public void setInheritShowWhenLocked(boolean inheritShowWhenLocked) { - try { - ActivityTaskManager.getService().setInheritShowWhenLocked( - mToken, inheritShowWhenLocked); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + ActivityClient.getInstance().setInheritShowWhenLocked(mToken, inheritShowWhenLocked); } /** @@ -8741,11 +8593,7 @@ public class Activity extends ContextThemeWrapper * @see KeyguardManager#isDeviceSecure() */ public void setTurnScreenOn(boolean turnScreenOn) { - try { - ActivityTaskManager.getService().setTurnScreenOn(mToken, turnScreenOn); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + ActivityClient.getInstance().setTurnScreenOn(mToken, turnScreenOn); } /** @@ -8757,11 +8605,7 @@ public class Activity extends ContextThemeWrapper */ @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS) public void registerRemoteAnimations(RemoteAnimationDefinition definition) { - try { - ActivityTaskManager.getService().registerRemoteAnimations(mToken, definition); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + ActivityClient.getInstance().registerRemoteAnimations(mToken, definition); } /** @@ -8771,11 +8615,7 @@ public class Activity extends ContextThemeWrapper */ @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS) public void unregisterRemoteAnimations() { - try { - ActivityTaskManager.getService().unregisterRemoteAnimations(mToken); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + ActivityClient.getInstance().unregisterRemoteAnimations(mToken); } class HostCallbacks extends FragmentHostCallback<Activity> { diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java new file mode 100644 index 000000000000..84ecd24b8c55 --- /dev/null +++ b/core/java/android/app/ActivityClient.java @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.IBinder; +import android.os.PersistableBundle; +import android.os.RemoteException; +import android.util.Singleton; +import android.view.RemoteAnimationDefinition; + +/** + * Provides the activity associated operations that communicate with system. + * + * @hide + */ +public class ActivityClient { + private ActivityClient() {} + + /** Reports the main thread is idle after the activity is resumed. */ + public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { + try { + getActivityClientController().activityIdle(token, config, stopProfiling); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** Reports {@link Activity#onResume()} is done. */ + public void activityResumed(IBinder token) { + try { + getActivityClientController().activityResumed(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Reports after {@link Activity#onTopResumedActivityChanged(boolean)} is called for losing the + * top most position. + */ + public void activityTopResumedStateLost() { + try { + getActivityClientController().activityTopResumedStateLost(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** Reports {@link Activity#onPause()} is done. */ + public void activityPaused(IBinder token) { + try { + getActivityClientController().activityPaused(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** Reports {@link Activity#onStop()} is done. */ + public void activityStopped(IBinder token, Bundle state, PersistableBundle persistentState, + CharSequence description) { + try { + getActivityClientController().activityStopped(token, state, persistentState, + description); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** Reports {@link Activity#onDestroy()} is done. */ + public void activityDestroyed(IBinder token) { + try { + getActivityClientController().activityDestroyed(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** Reports the activity has completed relaunched. */ + public void activityRelaunched(IBinder token) { + try { + getActivityClientController().activityRelaunched(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration, + int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) { + try { + getActivityClientController().reportSizeConfigurations(token, + horizontalSizeConfiguration, verticalSizeConfigurations, + smallestSizeConfigurations); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) { + try { + return getActivityClientController().moveActivityTaskToBack(token, nonRoot); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean shouldUpRecreateTask(IBinder token, String destAffinity) { + try { + return getActivityClientController().shouldUpRecreateTask(token, destAffinity); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode, + Intent resultData) { + try { + return getActivityClientController().navigateUpTo(token, destIntent, resultCode, + resultData); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean releaseActivityInstance(IBinder token) { + try { + return getActivityClientController().releaseActivityInstance(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public boolean finishActivity(IBinder token, int resultCode, Intent resultData, + int finishTask) { + try { + return getActivityClientController().finishActivity(token, resultCode, resultData, + finishTask); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean finishActivityAffinity(IBinder token) { + try { + return getActivityClientController().finishActivityAffinity(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void finishSubActivity(IBinder token, String resultWho, int requestCode) { + try { + getActivityClientController().finishSubActivity(token, resultWho, requestCode); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + public boolean isTopOfTask(IBinder token) { + try { + return getActivityClientController().isTopOfTask(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean willActivityBeVisible(IBinder token) { + try { + return getActivityClientController().willActivityBeVisible(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public int getDisplayId(IBinder token) { + try { + return getActivityClientController().getDisplayId(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public int getTaskForActivity(IBinder token, boolean onlyRoot) { + try { + return getActivityClientController().getTaskForActivity(token, onlyRoot); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + ComponentName getCallingActivity(IBinder token) { + try { + return getActivityClientController().getCallingActivity(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + String getCallingPackage(IBinder token) { + try { + return getActivityClientController().getCallingPackage(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + Bundle getActivityOptions(IBinder token) { + try { + return getActivityClientController().getActivityOptions(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public void setRequestedOrientation(IBinder token, int requestedOrientation) { + try { + getActivityClientController().setRequestedOrientation(token, requestedOrientation); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + int getRequestedOrientation(IBinder token) { + try { + return getActivityClientController().getRequestedOrientation(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean convertFromTranslucent(IBinder token) { + try { + return getActivityClientController().convertFromTranslucent(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean convertToTranslucent(IBinder token, Bundle options) { + try { + return getActivityClientController().convertToTranslucent(token, options); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) { + try { + getActivityClientController().reportActivityFullyDrawn(token, restoredFromBundle); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + boolean isImmersive(IBinder token) { + try { + return getActivityClientController().isImmersive(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void setImmersive(IBinder token, boolean immersive) { + try { + getActivityClientController().setImmersive(token, immersive); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + boolean enterPictureInPictureMode(IBinder token, PictureInPictureParams params) { + try { + return getActivityClientController().enterPictureInPictureMode(token, params); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void setPictureInPictureParams(IBinder token, PictureInPictureParams params) { + try { + getActivityClientController().setPictureInPictureParams(token, params); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void toggleFreeformWindowingMode(IBinder token) { + try { + getActivityClientController().toggleFreeformWindowingMode(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void startLockTaskModeByToken(IBinder token) { + try { + getActivityClientController().startLockTaskModeByToken(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void stopLockTaskModeByToken(IBinder token) { + try { + getActivityClientController().stopLockTaskModeByToken(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void showLockTaskEscapeMessage(IBinder token) { + try { + getActivityClientController().showLockTaskEscapeMessage(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) { + try { + getActivityClientController().setTaskDescription(token, td); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + boolean showAssistFromActivity(IBinder token, Bundle args) { + try { + return getActivityClientController().showAssistFromActivity(token, args); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + boolean isRootVoiceInteraction(IBinder token) { + try { + return getActivityClientController().isRootVoiceInteraction(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) { + try { + getActivityClientController().startLocalVoiceInteraction(callingActivity, options); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void stopLocalVoiceInteraction(IBinder callingActivity) { + try { + getActivityClientController().stopLocalVoiceInteraction(callingActivity); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void setShowWhenLocked(IBinder token, boolean showWhenLocked) { + try { + getActivityClientController().setShowWhenLocked(token, showWhenLocked); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) { + try { + getActivityClientController().setInheritShowWhenLocked(token, inheritShowWhenLocked); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void setTurnScreenOn(IBinder token, boolean turnScreenOn) { + try { + getActivityClientController().setTurnScreenOn(token, turnScreenOn); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + int setVrMode(IBinder token, boolean enabled, ComponentName packageName) { + try { + return getActivityClientController().setVrMode(token, enabled, packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void overridePendingTransition(IBinder token, String packageName, + int enterAnim, int exitAnim) { + try { + getActivityClientController().overridePendingTransition(token, packageName, + enterAnim, exitAnim); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void setDisablePreviewScreenshots(IBinder token, boolean disable) { + try { + getActivityClientController().setDisablePreviewScreenshots(token, disable); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) { + try { + getActivityClientController().registerRemoteAnimations(token, definition); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void unregisterRemoteAnimations(IBinder token) { + try { + getActivityClientController().unregisterRemoteAnimations(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + void onBackPressedOnTaskRoot(IBinder token) { + try { + getActivityClientController().onBackPressedOnTaskRoot(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + public static ActivityClient getInstance() { + return sInstance.get(); + } + + private static IActivityClientController getActivityClientController() { + return sActivityClientController.get(); + } + + private static final Singleton<ActivityClient> sInstance = new Singleton<ActivityClient>() { + @Override + protected ActivityClient create() { + return new ActivityClient(); + } + }; + + private static final Singleton<IActivityClientController> sActivityClientController = + new Singleton<IActivityClientController>() { + @Override + protected IActivityClientController create() { + try { + return ActivityTaskManager.getService().getActivityClientController(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + }; +} diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 2e08fc80b179..433182b38efd 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2154,7 +2154,7 @@ public final class ActivityThread extends ClientTransactionHandler { } if (a != null) { mNewActivities = null; - IActivityTaskManager am = ActivityTaskManager.getService(); + final ActivityClient ac = ActivityClient.getInstance(); ActivityClientRecord prev; do { if (localLOGV) Slog.v( @@ -2162,12 +2162,8 @@ public final class ActivityThread extends ClientTransactionHandler { " finished=" + (a.activity != null && a.activity.mFinished)); if (a.activity != null && !a.activity.mFinished) { - try { - am.activityIdle(a.token, a.createdConfig, stopProfiling); - a.createdConfig = null; - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + ac.activityIdle(a.token, a.createdConfig, stopProfiling); + a.createdConfig = null; } prev = a; a = a.nextIdle; @@ -3576,13 +3572,7 @@ public final class ActivityThread extends ClientTransactionHandler { } private ContextImpl createBaseContextForActivity(ActivityClientRecord r) { - final int displayId; - try { - displayId = ActivityTaskManager.getService().getDisplayId(r.token); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - + final int displayId = ActivityClient.getInstance().getDisplayId(r.token); ContextImpl appContext = ContextImpl.createActivityContext( this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig); @@ -3669,13 +3659,8 @@ public final class ActivityThread extends ClientTransactionHandler { } } else { // If there was an error, for any reason, tell the activity manager to stop us. - try { - ActivityTaskManager.getService() - .finishActivity(r.token, Activity.RESULT_CANCELED, null, - Activity.DONT_FINISH_TASK_WITH_ACTIVITY); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED, + null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } return a; @@ -3705,12 +3690,8 @@ public final class ActivityThread extends ClientTransactionHandler { smallest.put(config.smallestScreenWidthDp, 0); } } - try { - ActivityTaskManager.getService().reportSizeConfigurations(r.token, - horizontal.copyKeys(), vertical.copyKeys(), smallest.copyKeys()); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + ActivityClient.getInstance().reportSizeConfigurations(r.token, horizontal.copyKeys(), + vertical.copyKeys(), smallest.copyKeys()); } private void deliverNewIntents(ActivityClientRecord r, List<ReferrerIntent> intents) { @@ -4559,12 +4540,8 @@ public final class ActivityThread extends ClientTransactionHandler { // then go ahead and add the window. boolean willBeVisible = !a.mStartedActivity; if (!willBeVisible) { - try { - willBeVisible = ActivityTaskManager.getService().willActivityBeVisible( - a.getActivityToken()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + willBeVisible = ActivityClient.getInstance().willActivityBeVisible( + a.getActivityToken()); } if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); @@ -5209,11 +5186,7 @@ public final class ActivityThread extends ClientTransactionHandler { ((ContextImpl) c).scheduleFinalCleanup(r.activity.getClass().getName(), "Activity"); } if (finishing) { - try { - ActivityTaskManager.getService().activityDestroyed(r.token); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + ActivityClient.getInstance().activityDestroyed(r.token); } mSomeActivitiesChanged = true; } @@ -5477,13 +5450,9 @@ public final class ActivityThread extends ClientTransactionHandler { @Override public void reportRelaunch(ActivityClientRecord r, PendingTransactionActions pendingActions) { - try { - ActivityTaskManager.getService().activityRelaunched(r.token); - if (pendingActions.shouldReportRelaunchToWindowManager() && r.window != null) { - r.window.reportActivityRelaunched(); - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + ActivityClient.getInstance().activityRelaunched(r.token); + if (pendingActions.shouldReportRelaunchToWindowManager() && r.window != null) { + r.window.reportActivityRelaunched(); } } diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl new file mode 100644 index 000000000000..f9449f241545 --- /dev/null +++ b/core/java/android/app/IActivityClientController.aidl @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.app.ActivityManager; +import android.app.PictureInPictureParams; +import android.content.ComponentName; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.PersistableBundle; +import android.view.RemoteAnimationDefinition; + +/** + * Interface for the callback and request from an activity to system. + * + * {@hide} + */ +interface IActivityClientController { + oneway void activityIdle(in IBinder token, in Configuration config, in boolean stopProfiling); + void activityResumed(in IBinder token); + void activityTopResumedStateLost(); + void activityPaused(in IBinder token); + void activityStopped(in IBinder token, in Bundle state, in PersistableBundle persistentState, + in CharSequence description); + oneway void activityDestroyed(in IBinder token); + void activityRelaunched(in IBinder token); + + void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration, + in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations); + boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot); + boolean shouldUpRecreateTask(in IBinder token, in String destAffinity); + boolean navigateUpTo(in IBinder token, in Intent target, int resultCode, + in Intent resultData); + boolean releaseActivityInstance(in IBinder token); + boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask); + boolean finishActivityAffinity(in IBinder token); + /** Finish all activities that were started for result from the specified activity. */ + void finishSubActivity(in IBinder token, in String resultWho, int requestCode); + + boolean isTopOfTask(in IBinder token); + boolean willActivityBeVisible(in IBinder token); + int getDisplayId(in IBinder activityToken); + int getTaskForActivity(in IBinder token, in boolean onlyRoot); + ComponentName getCallingActivity(in IBinder token); + String getCallingPackage(in IBinder token); + Bundle getActivityOptions(in IBinder token); + + void setRequestedOrientation(in IBinder token, int requestedOrientation); + int getRequestedOrientation(in IBinder token); + + boolean convertFromTranslucent(in IBinder token); + boolean convertToTranslucent(in IBinder token, in Bundle options); + + boolean isImmersive(in IBinder token); + void setImmersive(in IBinder token, boolean immersive); + + boolean enterPictureInPictureMode(in IBinder token, in PictureInPictureParams params); + void setPictureInPictureParams(in IBinder token, in PictureInPictureParams params); + void toggleFreeformWindowingMode(in IBinder token); + + void startLockTaskModeByToken(in IBinder token); + void stopLockTaskModeByToken(in IBinder token); + oneway void showLockTaskEscapeMessage(in IBinder token); + void setTaskDescription(in IBinder token, in ActivityManager.TaskDescription values); + + boolean showAssistFromActivity(in IBinder token, in Bundle args); + boolean isRootVoiceInteraction(in IBinder token); + void startLocalVoiceInteraction(in IBinder token, in Bundle options); + void stopLocalVoiceInteraction(in IBinder token); + + void setShowWhenLocked(in IBinder token, boolean showWhenLocked); + void setInheritShowWhenLocked(in IBinder token, boolean setInheritShownWhenLocked); + void setTurnScreenOn(in IBinder token, boolean turnScreenOn); + void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle); + void overridePendingTransition(in IBinder token, in String packageName, + int enterAnim, int exitAnim); + int setVrMode(in IBinder token, boolean enabled, in ComponentName packageName); + + /** See {@link android.app.Activity#setDisablePreviewScreenshots}. */ + void setDisablePreviewScreenshots(in IBinder token, boolean disable); + + /** Registers remote animations for a specific activity. */ + void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition); + + /** Unregisters all remote animations for a specific activity. */ + void unregisterRemoteAnimations(in IBinder token); + + /** + * Reports that an Activity received a back key press when there were no additional activities + * on the back stack. + */ + void onBackPressedOnTaskRoot(in IBinder token); +} diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index ab48baea48e8..4b2557389382 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -22,6 +22,7 @@ import android.app.ApplicationErrorReport; import android.app.ContentProviderHolder; import android.app.GrantedUriPermission; import android.app.IApplicationThread; +import android.app.IActivityClientController; import android.app.IActivityController; import android.app.IAppTask; import android.app.IAssistDataReceiver; @@ -35,7 +36,6 @@ import android.app.IUidObserver; import android.app.IUserSwitchObserver; import android.app.Notification; import android.app.PendingIntent; -import android.app.PictureInPictureParams; import android.app.ProfilerInfo; import android.app.WaitResult; import android.app.assist.AssistContent; @@ -63,7 +63,6 @@ import android.os.Debug; import android.os.IBinder; import android.os.IProgressListener; import android.os.ParcelFileDescriptor; -import android.os.PersistableBundle; import android.os.StrictMode; import android.os.WorkSource; import android.service.voice.IVoiceInteractionSession; @@ -144,54 +143,25 @@ interface IActivityTaskManager { int userId); void unhandledBack(); - boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask); - boolean finishActivityAffinity(in IBinder token); - - oneway void activityIdle(in IBinder token, in Configuration config, - in boolean stopProfiling); - void activityResumed(in IBinder token); - void activityTopResumedStateLost(); - void activityPaused(in IBinder token); - void activityStopped(in IBinder token, in Bundle state, - in PersistableBundle persistentState, in CharSequence description); - oneway void activityDestroyed(in IBinder token); - void activityRelaunched(in IBinder token); + + /** Returns an interface to control the activity related operations. */ + IActivityClientController getActivityClientController(); + int getFrontActivityScreenCompatMode(); void setFrontActivityScreenCompatMode(int mode); - String getCallingPackage(in IBinder token); - ComponentName getCallingActivity(in IBinder token); void setFocusedTask(int taskId); boolean removeTask(int taskId); void removeAllVisibleRecentTasks(); List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, boolean filterOnlyVisibleRecents); - boolean shouldUpRecreateTask(in IBinder token, in String destAffinity); - boolean navigateUpTo(in IBinder token, in Intent target, int resultCode, - in Intent resultData); void moveTaskToFront(in IApplicationThread app, in String callingPackage, int task, int flags, in Bundle options); - int getTaskForActivity(in IBinder token, in boolean onlyRoot); - /** Finish all activities that were started for result from the specified activity. */ - void finishSubActivity(in IBinder token, in String resultWho, int requestCode); ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId); - boolean willActivityBeVisible(in IBinder token); - void setRequestedOrientation(in IBinder token, int requestedOrientation); - int getRequestedOrientation(in IBinder token); - boolean convertFromTranslucent(in IBinder token); - boolean convertToTranslucent(in IBinder token, in Bundle options); - void notifyActivityDrawn(in IBinder token); - void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle); - int getDisplayId(in IBinder activityToken); - boolean isImmersive(in IBinder token); - void setImmersive(in IBinder token, boolean immersive); boolean isTopActivityImmersive(); - boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot); ActivityManager.TaskDescription getTaskDescription(int taskId); - void overridePendingTransition(in IBinder token, in String packageName, - int enterAnim, int exitAnim); int getLaunchedFromUid(in IBinder activityToken); String getLaunchedFromPackage(in IBinder activityToken); - void reportAssistContextExtras(in IBinder token, in Bundle extras, + void reportAssistContextExtras(in IBinder assistToken, in Bundle extras, in AssistStructure structure, in AssistContent content, in Uri referrer); void setFocusedRootTask(int taskId); @@ -199,24 +169,16 @@ interface IActivityTaskManager { Rect getTaskBounds(int taskId); void cancelRecentsAnimation(boolean restoreHomeRootTaskPosition); - void startLockTaskModeByToken(in IBinder token); - void stopLockTaskModeByToken(in IBinder token); void updateLockTaskPackages(int userId, in String[] packages); boolean isInLockTaskMode(); int getLockTaskModeState(); - void setTaskDescription(in IBinder token, in ActivityManager.TaskDescription values); - Bundle getActivityOptions(in IBinder token); List<IBinder> getAppTasks(in String callingPackage); void startSystemLockTaskMode(int taskId); void stopSystemLockTaskMode(); void finishVoiceTask(in IVoiceInteractionSession session); - boolean isTopOfTask(in IBinder token); - void notifyLaunchTaskBehindComplete(in IBinder token); - void notifyEnterAnimationComplete(in IBinder token); int addAppTask(in IBinder activityToken, in Intent intent, in ActivityManager.TaskDescription description, in Bitmap thumbnail); Point getAppTaskThumbnailSize(); - boolean releaseActivityInstance(in IBinder token); /** * Only callable from the system. This token grants a temporary permission to call * #startActivityAsCallerWithToken. The token will time out after @@ -236,7 +198,6 @@ interface IActivityTaskManager { void registerTaskStackListener(in ITaskStackListener listener); void unregisterTaskStackListener(in ITaskStackListener listener); void setTaskResizeable(int taskId, int resizeableMode); - void toggleFreeformWindowingMode(in IBinder token); /** * Resize the task with given bounds @@ -287,9 +248,6 @@ interface IActivityTaskManager { boolean requestAutofillData(in IAssistDataReceiver receiver, in Bundle receiverExtras, in IBinder activityToken, int flags); boolean isAssistDataAllowedOnCurrentActivity(); - boolean showAssistFromActivity(in IBinder token, in Bundle args); - boolean isRootVoiceInteraction(in IBinder token); - oneway void showLockTaskEscapeMessage(in IBinder token); /** * Notify the system that the keyguard is going away. @@ -302,15 +260,9 @@ interface IActivityTaskManager { ComponentName getActivityClassForToken(in IBinder token); String getPackageForToken(in IBinder token); - void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration, - in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations); - void suppressResizeConfigChanges(boolean suppress); boolean moveTopActivityToPinnedRootTask(int rootTaskId, in Rect bounds); - boolean enterPictureInPictureMode(in IBinder token, in PictureInPictureParams params); - void setPictureInPictureParams(in IBinder token, in PictureInPictureParams params); void requestPictureInPictureMode(in IBinder token); - IBinder getUriPermissionOwnerForActivity(in IBinder activityToken); /** * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change. @@ -343,9 +295,6 @@ interface IActivityTaskManager { * are changing the docked stack size. */ void setSplitScreenResizing(boolean resizing); - int setVrMode(in IBinder token, boolean enabled, in ComponentName packageName); - void startLocalVoiceInteraction(in IBinder token, in Bundle options); - void stopLocalVoiceInteraction(in IBinder token); boolean supportsLocalVoiceInteraction(); // Get device configuration @@ -366,11 +315,6 @@ interface IActivityTaskManager { ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution); /** - * See {@link android.app.Activity#setDisablePreviewScreenshots} - */ - void setDisablePreviewScreenshots(IBinder token, boolean disable); - - /** * It should only be called from home activity to remove its outdated snapshot. The home * snapshot is used to speed up entering home from screen off. If the content of home activity * is significantly different from before taking the snapshot, then the home activity can use @@ -393,20 +337,6 @@ interface IActivityTaskManager { boolean updateConfiguration(in Configuration values); void updateLockTaskFeatures(int userId, int flags); - void setShowWhenLocked(in IBinder token, boolean showWhenLocked); - void setInheritShowWhenLocked(in IBinder token, boolean setInheritShownWhenLocked); - void setTurnScreenOn(in IBinder token, boolean turnScreenOn); - - /** - * Registers remote animations for a specific activity. - */ - void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition); - - /** - * Unregisters all remote animations for a specific activity. - */ - void unregisterRemoteAnimations(in IBinder token); - /** * Registers a remote animation to be run for all activity starts from a certain package during * a short predefined amount of time. @@ -448,10 +378,4 @@ interface IActivityTaskManager { * @param activityToken The token of the target activity to restart. */ void restartActivityProcessIfVisible(in IBinder activityToken); - - /** - * Reports that an Activity received a back key press when there were no additional activities - * on the back stack. - */ - void onBackPressedOnTaskRoot(in IBinder activityToken); } diff --git a/core/java/android/app/servertransaction/PauseActivityItem.java b/core/java/android/app/servertransaction/PauseActivityItem.java index f7c645e7cb38..813e0f93a1f7 100644 --- a/core/java/android/app/servertransaction/PauseActivityItem.java +++ b/core/java/android/app/servertransaction/PauseActivityItem.java @@ -20,12 +20,11 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityTaskManager; +import android.app.ActivityClient; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; -import android.os.RemoteException; import android.os.Trace; /** @@ -61,12 +60,8 @@ public class PauseActivityItem extends ActivityLifecycleItem { if (mDontReport) { return; } - try { - // TODO(lifecycler): Use interface callback instead of AMS. - ActivityTaskManager.getService().activityPaused(token); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + // TODO(lifecycler): Use interface callback instead of actual implementation. + ActivityClient.getInstance().activityPaused(token); } diff --git a/core/java/android/app/servertransaction/PendingTransactionActions.java b/core/java/android/app/servertransaction/PendingTransactionActions.java index 52ba8fb73f5f..a47fe821cd01 100644 --- a/core/java/android/app/servertransaction/PendingTransactionActions.java +++ b/core/java/android/app/servertransaction/PendingTransactionActions.java @@ -18,13 +18,11 @@ package android.app.servertransaction; import static android.app.ActivityThread.DEBUG_MEMORY_TRIM; -import android.app.ActivityManager; -import android.app.ActivityTaskManager; +import android.app.ActivityClient; import android.app.ActivityThread.ActivityClientRecord; import android.os.Build; import android.os.Bundle; import android.os.PersistableBundle; -import android.os.RemoteException; import android.os.TransactionTooLargeException; import android.util.Log; import android.util.LogWriter; @@ -142,9 +140,9 @@ public class PendingTransactionActions { try { if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + mActivity); // TODO(lifecycler): Use interface callback instead of AMS. - ActivityTaskManager.getService().activityStopped( + ActivityClient.getInstance().activityStopped( mActivity.token, mState, mPersistentState, mDescription); - } catch (RemoteException ex) { + } catch (RuntimeException ex) { // Dump statistics about bundle to help developers debug final LogWriter writer = new LogWriter(Log.WARN, TAG); final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -153,12 +151,12 @@ public class PendingTransactionActions { pw.println("PersistableBundle stats:"); Bundle.dumpStats(pw, mPersistentState); - if (ex instanceof TransactionTooLargeException + if (ex.getCause() instanceof TransactionTooLargeException && mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) { Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex); return; } - throw ex.rethrowFromSystemServer(); + throw ex; } } } diff --git a/core/java/android/app/servertransaction/ResumeActivityItem.java b/core/java/android/app/servertransaction/ResumeActivityItem.java index b4523f581ba8..d451599cc7b0 100644 --- a/core/java/android/app/servertransaction/ResumeActivityItem.java +++ b/core/java/android/app/servertransaction/ResumeActivityItem.java @@ -20,13 +20,12 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityClient; import android.app.ActivityManager; -import android.app.ActivityTaskManager; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; -import android.os.RemoteException; import android.os.Trace; /** @@ -60,12 +59,8 @@ public class ResumeActivityItem extends ActivityLifecycleItem { @Override public void postExecute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { - try { - // TODO(lifecycler): Use interface callback instead of AMS. - ActivityTaskManager.getService().activityResumed(token); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + // TODO(lifecycler): Use interface callback instead of actual implementation. + ActivityClient.getInstance().activityResumed(token); } @Override diff --git a/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java b/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java index 2b0c1b9869e0..5cd3d68f0326 100644 --- a/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java +++ b/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java @@ -19,12 +19,11 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityTaskManager; +import android.app.ActivityClient; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; -import android.os.RemoteException; import android.os.Trace; /** @@ -56,11 +55,7 @@ public class TopResumedActivityChangeItem extends ActivityTransactionItem { // 2. Activity wasn't RESUMED yet, which means that it didn't receive the top state yet. // 3. Activity is PAUSED or in other lifecycle state after PAUSED. In this case top resumed // state loss was already called right before pausing. - try { - ActivityTaskManager.getService().activityTopResumedStateLost(); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } + ActivityClient.getInstance().activityTopResumedStateLost(); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a5c66537b11f..29cc4b507acc 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -27953,10 +27953,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Requests pointer capture mode. * <p> * When the window has pointer capture, the mouse pointer icon will disappear and will not - * change its position. Further mouse will be dispatched with the source - * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available - * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events - * (touchscreens, or stylus) will not be affected. + * change its position. Enabling pointer capture will change the behavior of input devices in + * the following ways: + * <ul> + * <li>Events from a mouse will be delivered with the source + * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be + * available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li> + * + * <li>Events from a touchpad will be delivered with the source + * {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers + * on the touchpad will be available through {@link MotionEvent#getX(int)} and + * {@link MotionEvent#getY(int)}, and their relative movements are stored in + * {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li> + * + * <li>Events from other types of devices, such as touchscreens, will not be affected.</li> + * </ul> + * <p> + * Events captured through pointer capture will be dispatched to + * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an + * {@link OnCapturedPointerListener} is set, and otherwise to + * {@link #onCapturedPointerEvent(MotionEvent)}. * <p> * If the window already has pointer capture, this call does nothing. * <p> @@ -27965,6 +27981,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @see #releasePointerCapture() * @see #hasPointerCapture() + * @see #onPointerCaptureChange(boolean) */ public void requestPointerCapture() { final ViewRootImpl viewRootImpl = getViewRootImpl(); @@ -27980,6 +27997,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * If the window does not have pointer capture, this call will do nothing. * @see #requestPointerCapture() * @see #hasPointerCapture() + * @see #onPointerCaptureChange(boolean) */ public void releasePointerCapture() { final ViewRootImpl viewRootImpl = getViewRootImpl(); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 9c163783124e..13d9eb9d3c7d 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -45,7 +45,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.RemoteException; import android.transition.Scene; import android.transition.Transition; import android.transition.TransitionManager; @@ -635,7 +634,7 @@ public abstract class Window { * Moves the activity between {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing * mode and {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. */ - void toggleFreeformWindowingMode() throws RemoteException; + void toggleFreeformWindowingMode(); /** * Puts the activity in picture-in-picture mode if the activity supports. diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 2e3d560ccb56..9668c3b0af1c 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -162,6 +162,9 @@ public class ChooserActivity extends ResolverActivity implements private AppPredictor mWorkAppPredictor; private boolean mShouldDisplayLandscape; + private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4; + private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8; + @UnsupportedAppUsage public ChooserActivity() { } @@ -905,7 +908,7 @@ public class ChooserActivity extends ResolverActivity implements adapter, getPersonalProfileUserHandle(), /* workProfileUserHandle= */ null, - isSendAction(getTargetIntent())); + isSendAction(getTargetIntent()), getMaxTargetsPerRow()); } private ChooserMultiProfilePagerAdapter createChooserMultiProfilePagerAdapterForTwoProfiles( @@ -934,7 +937,7 @@ public class ChooserActivity extends ResolverActivity implements selectedProfile, getPersonalProfileUserHandle(), getWorkProfileUserHandle(), - isSendAction(getTargetIntent())); + isSendAction(getTargetIntent()), getMaxTargetsPerRow()); } private int findSelectedProfile() { @@ -2683,7 +2686,7 @@ public class ChooserActivity extends ResolverActivity implements // and b/150936654 recyclerView.setAdapter(gridAdapter); ((GridLayoutManager) recyclerView.getLayoutManager()).setSpanCount( - gridAdapter.getMaxTargetsPerRow()); + getMaxTargetsPerRow()); } UserHandle currentUserHandle = mChooserMultiProfilePagerAdapter.getCurrentUserHandle(); @@ -2848,9 +2851,7 @@ public class ChooserActivity extends ResolverActivity implements @Override // ChooserListCommunicator public int getMaxRankedTargets() { - return mChooserMultiProfilePagerAdapter.getCurrentRootAdapter() == null - ? ChooserGridAdapter.MAX_TARGETS_PER_ROW_PORTRAIT - : mChooserMultiProfilePagerAdapter.getCurrentRootAdapter().getMaxTargetsPerRow(); + return getMaxTargetsPerRow(); } @Override // ChooserListCommunicator @@ -3198,6 +3199,13 @@ public class ChooserActivity extends ResolverActivity implements } } + int getMaxTargetsPerRow() { + int maxTargets = MAX_TARGETS_PER_ROW_PORTRAIT; + if (mShouldDisplayLandscape) { + maxTargets = MAX_TARGETS_PER_ROW_LANDSCAPE; + } + return maxTargets; + } /** * Adapter for all types of items and targets in ShareSheet. * Note that ranked sections like Direct Share - while appearing grid-like - are handled on the @@ -3226,9 +3234,6 @@ public class ChooserActivity extends ResolverActivity implements private static final int VIEW_TYPE_CALLER_AND_RANK = 5; private static final int VIEW_TYPE_FOOTER = 6; - private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4; - private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8; - private static final int NUM_EXPANSIONS_TO_HIDE_AZ_LABEL = 20; ChooserGridAdapter(ChooserListAdapter wrappedAdapter) { @@ -3277,14 +3282,6 @@ public class ChooserActivity extends ResolverActivity implements return false; } - int getMaxTargetsPerRow() { - int maxTargets = MAX_TARGETS_PER_ROW_PORTRAIT; - if (mShouldDisplayLandscape) { - maxTargets = MAX_TARGETS_PER_ROW_LANDSCAPE; - } - return maxTargets; - } - /** * Hides the list item content preview. * <p>Not to be confused with the sticky content preview which is above the @@ -3654,8 +3651,7 @@ public class ChooserActivity extends ResolverActivity implements position -= getSystemRowCount() + getProfileRowCount(); final int serviceCount = mChooserListAdapter.getServiceTargetCount(); - final int serviceRows = (int) Math.ceil((float) serviceCount - / ChooserListAdapter.MAX_SERVICE_TARGETS); + final int serviceRows = (int) Math.ceil((float) serviceCount / getMaxRankedTargets()); if (position < serviceRows) { return position * getMaxTargetsPerRow(); } diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index 00b5cb646bca..570066807f16 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -82,8 +82,6 @@ public class ChooserListAdapter extends ResolverListAdapter { private static final int MAX_SERVICE_TARGET_APP = 8; private static final int DEFAULT_DIRECT_SHARE_RANKING_SCORE = 1000; - static final int MAX_SERVICE_TARGETS = 8; - /** {@link #getBaseScore} */ public static final float CALLER_TARGET_SCORE_BOOST = 900.f; /** {@link #getBaseScore} */ @@ -130,10 +128,10 @@ public class ChooserListAdapter extends ResolverListAdapter { super(context, payloadIntents, null, rList, filterLastUsed, resolverListController, chooserListCommunicator, false); - createPlaceHolders(); mMaxShortcutTargetsPerApp = context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp); mChooserListCommunicator = chooserListCommunicator; + createPlaceHolders(); mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator; if (initialIntents != null) { @@ -227,7 +225,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mParkingDirectShareTargets.clear(); mPendingChooserTargetService.clear(); mShortcutComponents.clear(); - for (int i = 0; i < MAX_SERVICE_TARGETS; i++) { + for (int i = 0; i < mChooserListCommunicator.getMaxRankedTargets(); i++) { mServiceTargets.add(mPlaceHolderTargetInfo); } } @@ -382,7 +380,7 @@ public class ChooserListAdapter extends ResolverListAdapter { public int getServiceTargetCount() { if (mChooserListCommunicator.isSendAction(mChooserListCommunicator.getTargetIntent()) && !ActivityManager.isLowRamDeviceStatic()) { - return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS); + return Math.min(mServiceTargets.size(), mChooserListCommunicator.getMaxRankedTargets()); } return 0; @@ -847,7 +845,8 @@ public class ChooserListAdapter extends ResolverListAdapter { int currentSize = mServiceTargets.size(); final float newScore = chooserTargetInfo.getModifiedScore(); - for (int i = 0; i < Math.min(currentSize, MAX_SERVICE_TARGETS); i++) { + for (int i = 0; i < Math.min(currentSize, mChooserListCommunicator.getMaxRankedTargets()); + i++) { final ChooserTargetInfo serviceTarget = mServiceTargets.get(i); if (serviceTarget == null) { mServiceTargets.set(i, chooserTargetInfo); @@ -858,7 +857,7 @@ public class ChooserListAdapter extends ResolverListAdapter { } } - if (currentSize < MAX_SERVICE_TARGETS) { + if (currentSize < mChooserListCommunicator.getMaxRankedTargets()) { mServiceTargets.add(chooserTargetInfo); return true; } diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java index 3a65a324f9d6..dd837fc2194c 100644 --- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java @@ -39,17 +39,19 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd private final ChooserProfileDescriptor[] mItems; private final boolean mIsSendAction; private int mBottomOffset; + private int mMaxTargetsPerRow; ChooserMultiProfilePagerAdapter(Context context, ChooserActivity.ChooserGridAdapter adapter, UserHandle personalProfileUserHandle, UserHandle workProfileUserHandle, - boolean isSendAction) { + boolean isSendAction, int maxTargetsPerRow) { super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle); mItems = new ChooserProfileDescriptor[] { createProfileDescriptor(adapter) }; mIsSendAction = isSendAction; + mMaxTargetsPerRow = maxTargetsPerRow; } ChooserMultiProfilePagerAdapter(Context context, @@ -58,7 +60,7 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd @Profile int defaultProfile, UserHandle personalProfileUserHandle, UserHandle workProfileUserHandle, - boolean isSendAction) { + boolean isSendAction, int maxTargetsPerRow) { super(context, /* currentPage */ defaultProfile, personalProfileUserHandle, workProfileUserHandle); mItems = new ChooserProfileDescriptor[] { @@ -66,6 +68,7 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd createProfileDescriptor(workAdapter) }; mIsSendAction = isSendAction; + mMaxTargetsPerRow = maxTargetsPerRow; } private ChooserProfileDescriptor createProfileDescriptor( @@ -114,7 +117,7 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd ChooserActivity.ChooserGridAdapter chooserGridAdapter = getItem(pageIndex).chooserGridAdapter; GridLayoutManager glm = (GridLayoutManager) recyclerView.getLayoutManager(); - glm.setSpanCount(chooserGridAdapter.getMaxTargetsPerRow()); + glm.setSpanCount(mMaxTargetsPerRow); glm.setSpanSizeLookup( new GridLayoutManager.SpanSizeLookup() { @Override diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java index 21021457377a..362fd7b4e937 100644 --- a/core/java/com/android/internal/widget/DecorCaptionView.java +++ b/core/java/com/android/internal/widget/DecorCaptionView.java @@ -18,9 +18,7 @@ package com.android.internal.widget; import android.content.Context; import android.graphics.Rect; -import android.os.RemoteException; import android.util.AttributeSet; -import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; @@ -72,7 +70,6 @@ import java.util.ArrayList; */ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, GestureDetector.OnGestureListener { - private final static String TAG = "DecorCaptionView"; private PhoneWindow mOwner = null; private boolean mShow = false; @@ -327,11 +324,7 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, private void toggleFreeformWindowingMode() { Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback(); if (callback != null) { - try { - callback.toggleFreeformWindowingMode(); - } catch (RemoteException ex) { - Log.e(TAG, "Cannot change task workspace."); - } + callback.toggleFreeformWindowingMode(); } } diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index 46695d2764dd..a74f580b65e6 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -38,13 +38,11 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.app.Activity; -import android.app.ActivityTaskManager; +import android.app.ActivityClient; import android.app.ActivityThread; import android.app.ActivityThread.ActivityClientRecord; -import android.app.IActivityTaskManager; import android.app.LoadedApk; import android.app.servertransaction.PendingTransactionActions; import android.content.ComponentName; @@ -54,7 +52,6 @@ import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.os.IBinder; -import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.testing.PollingCheck; @@ -224,18 +221,19 @@ public class ActivityThreadClientTest { private MockitoSession mMockSession; private ActivityThread mThread; - private ClientMockSession() throws RemoteException { + private ClientMockSession() { mThread = ActivityThread.currentActivityThread(); mMockSession = mockitoSession() .strictness(Strictness.LENIENT) - .spyStatic(ActivityTaskManager.class) + .spyStatic(ActivityClient.class) .spyStatic(WindowManagerGlobal.class) .startMocking(); doReturn(Mockito.mock(WindowManagerGlobal.class)) .when(WindowManagerGlobal::getInstance); - IActivityTaskManager mockAtm = Mockito.mock(IActivityTaskManager.class); - doReturn(mockAtm).when(ActivityTaskManager::getService); - when(mockAtm.finishActivity(any(), anyInt(), any(), anyInt())).thenReturn(true); + final ActivityClient mockAc = Mockito.mock(ActivityClient.class); + doReturn(mockAc).when(ActivityClient::getInstance); + doReturn(true).when(mockAc).finishActivity(any() /* token */, + anyInt() /* resultCode */, any() /* resultData */, anyInt() /* finishTask */); } private Activity launchActivity(ActivityClientRecord r) { diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 6bcab8a34e2c..1dace8125ae1 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -799,12 +799,6 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-1155279885": { - "message": "Frontmost changed immersion: %s", - "level": "DEBUG", - "group": "WM_DEBUG_IMMERSIVE", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" - }, "-1144293044": { "message": "SURFACE SET FREEZE LAYER: %s", "level": "INFO", @@ -1219,6 +1213,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, + "-655104359": { + "message": "Frontmost changed immersion: %s", + "level": "DEBUG", + "group": "WM_DEBUG_IMMERSIVE", + "at": "com\/android\/server\/wm\/ActivityClientController.java" + }, "-653156702": { "message": "createAppAnimations()", "level": "DEBUG", @@ -1573,12 +1573,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/Task.java" }, - "-272719931": { - "message": "startLockTaskModeLocked: %s", - "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" - }, "-262984451": { "message": "Relaunch failed %s", "level": "INFO", @@ -2047,6 +2041,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DisplayRotation.java" }, + "295861935": { + "message": "startLockTaskMode: %s", + "level": "WARN", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + }, "302969511": { "message": "Task info changed taskId=%d", "level": "VERBOSE", @@ -2557,6 +2557,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/TaskDisplayArea.java" }, + "883475718": { + "message": "Report configuration: %s %s %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityClientController.java" + }, "892244061": { "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", "level": "INFO", @@ -3097,12 +3103,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1576607724": { - "message": "Report configuration: %s %s %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" - }, "1577579529": { "message": "win=%s destroySurfaces: appStopped=%b win.mWindowRemovalAllowed=%b win.mRemoveOnExit=%b", "level": "ERROR", diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LogConfig.java b/packages/SystemUI/src/com/android/systemui/screenshot/LogConfig.java new file mode 100644 index 000000000000..6050c2b90e34 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/screenshot/LogConfig.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.screenshot; + +@SuppressWarnings("PointlessBooleanExpression") +class LogConfig { + + /** Log ALL the things... */ + private static final boolean DEBUG_ALL = false; + + /** Default log logTag for screenshot code */ + private static final String TAG_SS = "Screenshot"; + + /** Use class name as Log tag instead of the default */ + private static final boolean TAG_WITH_CLASS_NAME = false; + + /** Action creation and user selection: Share, Save, Edit, Delete, Smart action, etc */ + static final boolean DEBUG_ACTIONS = DEBUG_ALL || false; + + /** Debug info about animations such as start, complete and cancel */ + static final boolean DEBUG_ANIM = DEBUG_ALL || false; + + /** Whenever Uri is supplied to consumer, or onComplete runnable is run() */ + static final boolean DEBUG_CALLBACK = DEBUG_ALL || false; + + /** Logs information about dismissing the screenshot tool */ + static final boolean DEBUG_DISMISS = DEBUG_ALL || false; + + /** Touch or key event driven action or side effects */ + static final boolean DEBUG_INPUT = DEBUG_ALL || false; + + /** Scroll capture usage */ + static final boolean DEBUG_SCROLL = DEBUG_ALL || false; + + /** Service lifecycle events and callbacks */ + static final boolean DEBUG_SERVICE = DEBUG_ALL || false; + + /** Storage related actions, Bitmap.compress, ContentManager, etc */ + static final boolean DEBUG_STORAGE = DEBUG_ALL || false; + + /** High level logical UI actions: timeout, onConfigChanged, insets, show actions, reset */ + static final boolean DEBUG_UI = DEBUG_ALL || false; + + /** Interactions with Window and WindowManager */ + static final boolean DEBUG_WINDOW = DEBUG_ALL || false; + + static String logTag(Class<?> cls) { + return TAG_WITH_CLASS_NAME ? cls.getSimpleName() : TAG_SS; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java index b2ebf3f700b9..f4ce77acb8ec 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java @@ -16,6 +16,11 @@ package com.android.systemui.screenshot; +import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS; +import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK; +import static com.android.systemui.screenshot.LogConfig.DEBUG_STORAGE; +import static com.android.systemui.screenshot.LogConfig.logTag; + import android.app.ActivityTaskManager; import android.app.Notification; import android.app.PendingIntent; @@ -45,7 +50,7 @@ import android.provider.MediaStore; import android.provider.MediaStore.MediaColumns; import android.text.TextUtils; import android.text.format.DateUtils; -import android.util.Slog; +import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; @@ -73,8 +78,8 @@ import java.util.concurrent.CompletableFuture; /** * An AsyncTask that saves an image to the media store in the background. */ -class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { - private static final String TAG = "SaveImageInBackgroundTask"; +class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { + private static final String TAG = logTag(SaveImageInBackgroundTask.class); private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; private static final String SCREENSHOT_ID_TEMPLATE = "Screenshot_%s"; @@ -121,6 +126,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... paramsUnused) { if (isCancelled()) { + if (DEBUG_STORAGE) { + Log.d(TAG, "cancelled! returning null"); + } return null; } Thread.currentThread().setPriority(Thread.MAX_PRIORITY); @@ -151,9 +159,19 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { try { // First, write the actual data for our screenshot try (OutputStream out = resolver.openOutputStream(uri)) { + if (DEBUG_STORAGE) { + Log.d(TAG, "Compressing PNG:" + + " w=" + image.getWidth() + " h=" + image.getHeight()); + } if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) { + if (DEBUG_STORAGE) { + Log.d(TAG, "Bitmap.compress returned false"); + } throw new IOException("Failed to compress"); } + if (DEBUG_STORAGE) { + Log.d(TAG, "Done compressing PNG"); + } } // Next, write metadata to help index the screenshot @@ -181,7 +199,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { exif.setAttribute(ExifInterface.TAG_OFFSET_TIME_ORIGINAL, DateTimeFormatter.ofPattern("XXX").format(time)); } - + if (DEBUG_STORAGE) { + Log.d(TAG, "Writing EXIF metadata"); + } exif.saveAttributes(); } @@ -190,6 +210,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { values.put(MediaColumns.IS_PENDING, 0); values.putNull(MediaColumns.DATE_EXPIRES); resolver.update(uri, values, null, null); + if (DEBUG_STORAGE) { + Log.d(TAG, "Completed writing to ContentManager"); + } } catch (Exception e) { resolver.delete(uri, null); throw e; @@ -215,15 +238,24 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri); mParams.mActionsReadyListener.onActionsReady(mImageData); + if (DEBUG_CALLBACK) { + Log.d(TAG, "finished background processing, Calling (Consumer<Uri>) " + + "finisher.accept(\"" + mImageData.uri + "\""); + } mParams.finisher.accept(mImageData.uri); mParams.image = null; } catch (Exception e) { // IOException/UnsupportedOperationException may be thrown if external storage is // not mounted - Slog.e(TAG, "unable to save screenshot", e); + if (DEBUG_STORAGE) { + Log.d(TAG, "Failed to store screenshot", e); + } mParams.clearImage(); mImageData.reset(); mParams.mActionsReadyListener.onActionsReady(mImageData); + if (DEBUG_CALLBACK) { + Log.d(TAG, "Calling (Consumer<Uri>) finisher.accept(null)"); + } mParams.finisher.accept(null); } @@ -245,6 +277,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { // params from the ctor in any case. mImageData.reset(); mParams.mActionsReadyListener.onActionsReady(mImageData); + if (DEBUG_CALLBACK) { + Log.d(TAG, "onCancelled, calling (Consumer<Uri>) finisher.accept(null)"); + } mParams.finisher.accept(null); mParams.clearImage(); } @@ -380,7 +415,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { try { return ActivityTaskManager.getService().getLastResumedActivityUserId(); } catch (RemoteException e) { - Slog.w(TAG, "getUserHandleOfForegroundApplication: ", e); + if (DEBUG_ACTIONS) { + Log.d(TAG, "Failed to get UserHandle of foreground app: ", e); + } return context.getUserId(); } } @@ -421,6 +458,4 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { .putExtra(ScreenshotController.EXTRA_ID, screenshotId) .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled); } - - } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index d7f9c6163b1d..6a4e93be0fe5 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -21,6 +21,14 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; +import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM; +import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK; +import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS; +import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT; +import static com.android.systemui.screenshot.LogConfig.DEBUG_UI; +import static com.android.systemui.screenshot.LogConfig.DEBUG_WINDOW; +import static com.android.systemui.screenshot.LogConfig.logTag; + import static java.util.Objects.requireNonNull; import android.animation.Animator; @@ -75,6 +83,7 @@ import javax.inject.Inject; * Controls the state and flow for screenshots. */ public class ScreenshotController { + private static final String TAG = logTag(ScreenshotController.class); /** * POD used in the AsyncTask which saves an image in the background. */ @@ -110,12 +119,10 @@ public class ScreenshotController { } } - abstract static class ActionsReadyListener { - abstract void onActionsReady(ScreenshotController.SavedImageData imageData); + interface ActionsReadyListener { + void onActionsReady(ScreenshotController.SavedImageData imageData); } - private static final String TAG = "ScreenshotController"; - // These strings are used for communicating the action invoked to // ScreenshotNotificationSmartActionsProvider. static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type"; @@ -166,6 +173,9 @@ public class ScreenshotController { public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_CORNER_TIMEOUT: + if (DEBUG_UI) { + Log.d(TAG, "Corner timeout hit"); + } mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_INTERACTION_TIMEOUT); ScreenshotController.this.dismissScreenshot(false); break; @@ -292,13 +302,17 @@ public class ScreenshotController { * Clears current screenshot */ void dismissScreenshot(boolean immediate) { + if (DEBUG_DISMISS) { + Log.d(TAG, "dismissScreenshot(immediate=" + immediate + ")"); + } // If we're already animating out, don't restart the animation // (but do obey an immediate dismissal) if (!immediate && mScreenshotView.isDismissing()) { - Log.v(TAG, "Already dismissing, ignoring duplicate command"); + if (DEBUG_DISMISS) { + Log.v(TAG, "Already dismissing, ignoring duplicate command"); + } return; } - Log.v(TAG, "Clearing screenshot"); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); if (immediate) { resetScreenshotView(); @@ -308,12 +322,17 @@ public class ScreenshotController { } /** - * Update assets (called when the dark theme status changes). We only need to update the dismiss - * button and the actions container background, since the buttons are re-inflated on demand. + * Update resources on configuration change. Reinflate for theme/color changes. */ private void reloadAssets() { + if (DEBUG_UI) { + Log.d(TAG, "reloadAssets()"); + } boolean wasAttached = mDecorView.isAttachedToWindow(); if (wasAttached) { + if (DEBUG_WINDOW) { + Log.d(TAG, "Removing screenshot window"); + } mWindowManager.removeView(mDecorView); } @@ -336,6 +355,9 @@ public class ScreenshotController { // TODO(159460485): Remove this when focus is handled properly in the system mScreenshotView.setOnTouchListener((v, event) -> { if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) { + if (DEBUG_INPUT) { + Log.d(TAG, "onTouch: ACTION_OUTSIDE"); + } // Once the user touches outside, stop listening for input setWindowFocusable(false); } @@ -344,6 +366,9 @@ public class ScreenshotController { mScreenshotView.setOnKeyListener((v, keyCode, event) -> { if (keyCode == KeyEvent.KEYCODE_BACK) { + if (DEBUG_INPUT) { + Log.d(TAG, "onKeyEvent: KeyEvent.KEYCODE_BACK"); + } dismissScreenshot(false); return true; } @@ -373,10 +398,16 @@ public class ScreenshotController { Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap(); if (screenshot == null) { - Log.e(TAG, "Screenshot bitmap was null"); + Log.e(TAG, "takeScreenshotInternal: Screenshot bitmap was null"); mNotificationsController.notifyScreenshotError( R.string.screenshot_failed_to_capture_text); + if (DEBUG_CALLBACK) { + Log.d(TAG, "Supplying null to Consumer<Uri>"); + } finisher.accept(null); + if (DEBUG_CALLBACK) { + Log.d(TAG, "Calling mOnCompleteRunnable.run()"); + } mOnCompleteRunnable.run(); return; } @@ -399,12 +430,17 @@ public class ScreenshotController { if (!mScreenshotView.isDismissing()) { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED); } + if (DEBUG_WINDOW) { + Log.d(TAG, "saveScreenshot: screenshotView is already attached, resetting. " + + "(dismissing=" + mScreenshotView.isDismissing() + ")"); + } mScreenshotView.reset(); } mScreenBitmap = screenshot; if (!isUserSetupComplete()) { + Log.w(TAG, "User setup not complete, displaying toast only"); // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing // and sharing shouldn't be exposed to the user. saveScreenshotAndToast(finisher); @@ -416,6 +452,9 @@ public class ScreenshotController { mScreenBitmap.prepareToDraw(); if (mConfigChanges.applyNewConfig(mContext.getResources())) { + if (DEBUG_UI) { + Log.d(TAG, "saveScreenshot: reloading assets"); + } reloadAssets(); } @@ -450,25 +489,21 @@ public class ScreenshotController { mCameraSound.play(MediaActionSound.SHUTTER_CLICK); }); - saveScreenshotInWorkerThread(finisher, - new ScreenshotController.ActionsReadyListener() { - @Override - void onActionsReady(ScreenshotController.SavedImageData imageData) { - finisher.accept(imageData.uri); - if (imageData.uri == null) { - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED); - mNotificationsController.notifyScreenshotError( - R.string.screenshot_failed_to_save_text); - } else { - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED); - - mScreenshotHandler.post(() -> { - Toast.makeText(mContext, R.string.screenshot_saved_title, - Toast.LENGTH_SHORT).show(); - }); - } - } - }); + saveScreenshotInWorkerThread(finisher, imageData -> { + if (DEBUG_CALLBACK) { + Log.d(TAG, "returning URI to finisher (Consumer<URI>): " + imageData.uri); + } + finisher.accept(imageData.uri); + if (imageData.uri == null) { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED); + mNotificationsController.notifyScreenshotError( + R.string.screenshot_failed_to_save_text); + } else { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED); + mScreenshotHandler.post(() -> Toast.makeText(mContext, + R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show()); + } + }); } /** @@ -479,37 +514,46 @@ public class ScreenshotController { mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotHandler.post(() -> { if (!mScreenshotView.isAttachedToWindow()) { + if (DEBUG_WINDOW) { + Log.d(TAG, "Adding screenshot window"); + } mWindowManager.addView(mWindow.getDecorView(), mWindowLayoutParams); } mScreenshotView.prepareForAnimation(mScreenBitmap, screenInsets); mScreenshotHandler.post(() -> { + if (DEBUG_WINDOW) { + Log.d(TAG, "adding OnComputeInternalInsetsListener"); + } mScreenshotView.getViewTreeObserver().addOnComputeInternalInsetsListener( mScreenshotView); mScreenshotAnimation = mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash); - saveScreenshotInWorkerThread(finisher, - new ScreenshotController.ActionsReadyListener() { - @Override - void onActionsReady( - ScreenshotController.SavedImageData imageData) { - showUiOnActionsReady(imageData); - } - }); + saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady); // Play the shutter sound to notify that we've taken a screenshot mCameraSound.play(MediaActionSound.SHUTTER_CLICK); + if (DEBUG_ANIM) { + Log.d(TAG, "starting post-screenshot animation"); + } mScreenshotAnimation.start(); }); }); } + /** Reset screenshot view and then call onCompleteRunnable */ private void resetScreenshotView() { + if (DEBUG_UI) { + Log.d(TAG, "resetScreenshotView"); + } if (mScreenshotView.isAttachedToWindow()) { + if (DEBUG_WINDOW) { + Log.d(TAG, "Removing screenshot window"); + } mWindowManager.removeView(mDecorView); } mScreenshotView.reset(); @@ -519,8 +563,7 @@ public class ScreenshotController { /** * Creates a new worker thread and saves the screenshot to the media store. */ - private void saveScreenshotInWorkerThread( - Consumer<Uri> finisher, + private void saveScreenshotInWorkerThread(Consumer<Uri> finisher, @Nullable ScreenshotController.ActionsReadyListener actionsReadyListener) { ScreenshotController.SaveImageInBackgroundData data = new ScreenshotController.SaveImageInBackgroundData(); @@ -530,13 +573,7 @@ public class ScreenshotController { if (mSaveInBgTask != null) { // just log success/failure for the pre-existing screenshot - mSaveInBgTask.setActionsReadyListener( - new ScreenshotController.ActionsReadyListener() { - @Override - void onActionsReady(ScreenshotController.SavedImageData imageData) { - logSuccessOnActionsReady(imageData); - } - }); + mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady); } mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data); @@ -555,6 +592,9 @@ public class ScreenshotController { SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS, AccessibilityManager.FLAG_CONTENT_CONTROLS); + if (DEBUG_UI) { + Log.d(TAG, "Showing UI actions, dismiss timeout: " + timeoutMs + " ms"); + } mScreenshotHandler.sendMessageDelayed( mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT), timeoutMs); @@ -600,6 +640,9 @@ public class ScreenshotController { * shown. */ private void setWindowFocusable(boolean focusable) { + if (DEBUG_WINDOW) { + Log.d(TAG, "setWindowFocusable: " + focusable); + } if (focusable) { mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; } else { @@ -618,9 +661,10 @@ public class ScreenshotController { if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0 || bitmap.getHeight() == 0) { - Log.e(TAG, String.format( - "Provided bitmap and insets create degenerate region: %dx%d %s", - bitmap.getWidth(), bitmap.getHeight(), bitmapInsets)); + if (DEBUG_UI) { + Log.e(TAG, "Provided bitmap and insets create degenerate region: " + + bitmap.getWidth() + "x" + bitmap.getHeight() + " " + bitmapInsets); + } return false; } @@ -628,11 +672,10 @@ public class ScreenshotController { float boundsAspect = ((float) screenBounds.width()) / screenBounds.height(); boolean matchWithinTolerance = Math.abs(insettedBitmapAspect - boundsAspect) < 0.1f; - if (!matchWithinTolerance) { - Log.d(TAG, String.format("aspectRatiosMatch: don't match bitmap: %f, bounds: %f", - insettedBitmapAspect, boundsAspect)); + if (DEBUG_UI) { + Log.d(TAG, "aspectRatiosMatch: don't match bitmap: " + insettedBitmapAspect + + ", bounds: " + boundsAspect); } - return matchWithinTolerance; } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java index 63f323ed2768..29f67f348f7b 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java @@ -16,6 +16,9 @@ package com.android.systemui.screenshot; +import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS; +import static com.android.systemui.screenshot.LogConfig.logTag; + import android.app.Notification; import android.content.ComponentName; import android.graphics.Bitmap; @@ -32,6 +35,9 @@ import java.util.concurrent.CompletableFuture; * in order to provide smart actions in the screenshot notification. */ public class ScreenshotNotificationSmartActionsProvider { + + private static final String TAG = logTag(ScreenshotNotificationSmartActionsProvider.class); + /* Key provided in the notification action to get the type of smart action. */ public static final String ACTION_TYPE = "action_type"; public static final String DEFAULT_ACTION_TYPE = "Smart Action"; @@ -51,29 +57,21 @@ public class ScreenshotNotificationSmartActionsProvider { ERROR, TIMEOUT } - - private static final String TAG = "ScreenshotActions"; - /** * Default implementation that returns an empty list. * This method is overridden in vendor-specific Sys UI implementation. * - * @param screenshotId A generated random unique id for the screenshot. - * @param screenshotFileName name of the file where the screenshot will be written. - * @param bitmap The bitmap of the screenshot. The bitmap config must be {@link - * HARDWARE}. - * @param componentName Contains package and activity class names where the screenshot was - * taken. This is used as an additional signal to generate and rank - * more relevant actions. - * @param userHandle The user handle of the app where the screenshot was taken. + * @param screenshotId a unique id for the screenshot + * @param screenshotUri uri where the screenshot has been stored + * @param bitmap the screenshot, config must be {@link Bitmap.Config#HARDWARE} + * @param componentName name of the foreground component when the screenshot was taken + * @param userHandle user handle of the foreground task owner */ - public CompletableFuture<List<Notification.Action>> getActions( - String screenshotId, - Uri screenshotUri, - Bitmap bitmap, - ComponentName componentName, - UserHandle userHandle) { - Log.d(TAG, "Returning empty smart action list."); + public CompletableFuture<List<Notification.Action>> getActions(String screenshotId, + Uri screenshotUri, Bitmap bitmap, ComponentName componentName, UserHandle userHandle) { + if (DEBUG_ACTIONS) { + Log.d(TAG, "Returning empty smart action list."); + } return CompletableFuture.completedFuture(Collections.emptyList()); } @@ -88,7 +86,9 @@ public class ScreenshotNotificationSmartActionsProvider { */ public void notifyOp(String screenshotId, ScreenshotOp op, ScreenshotOpStatus status, long durationMs) { - Log.d(TAG, "Return without notify."); + if (DEBUG_ACTIONS) { + Log.d(TAG, "SmartActions: notifyOp() - return without notify"); + } } /** @@ -100,6 +100,8 @@ public class ScreenshotNotificationSmartActionsProvider { * @param isSmartAction whether action invoked was a smart action. */ public void notifyAction(String screenshotId, String action, boolean isSmartAction) { - Log.d(TAG, "Return without notify."); + if (DEBUG_ACTIONS) { + Log.d(TAG, "SmartActions: notifyAction: return without notify"); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java index 468602a5369e..1184dc7fe1a4 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java @@ -18,6 +18,9 @@ package com.android.systemui.screenshot; import static android.os.AsyncTask.THREAD_POOL_EXECUTOR; +import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS; +import static com.android.systemui.screenshot.LogConfig.logTag; + import android.app.ActivityManager; import android.app.Notification; import android.content.ComponentName; @@ -27,7 +30,7 @@ import android.net.Uri; import android.os.Handler; import android.os.SystemClock; import android.os.UserHandle; -import android.util.Slog; +import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.SystemUIFactory; @@ -47,7 +50,7 @@ import javax.inject.Inject; */ @SysUISingleton public class ScreenshotSmartActions { - private static final String TAG = "ScreenshotSmartActions"; + private static final String TAG = logTag(ScreenshotSmartActions.class); @Inject public ScreenshotSmartActions() {} @@ -57,18 +60,24 @@ public class ScreenshotSmartActions { String screenshotId, Uri screenshotUri, Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider, boolean smartActionsEnabled, UserHandle userHandle) { + if (DEBUG_ACTIONS) { + Log.d(TAG, String.format("getSmartActionsFuture id=%s, uri=%s, provider=%s, " + + "smartActionsEnabled=%b, userHandle=%s", screenshotId, screenshotUri, + smartActionsProvider.getClass(), smartActionsEnabled, userHandle)); + } if (!smartActionsEnabled) { - Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list."); + if (DEBUG_ACTIONS) { + Log.d(TAG, "Screenshot Intelligence not enabled, returning empty list."); + } return CompletableFuture.completedFuture(Collections.emptyList()); } if (image.getConfig() != Bitmap.Config.HARDWARE) { - Slog.w(TAG, String.format( - "Bitmap expected: Hardware, Bitmap found: %s. Returning empty list.", - image.getConfig())); + if (DEBUG_ACTIONS) { + Log.d(TAG, String.format("Bitmap expected: Hardware, Bitmap found: %s. " + + "Returning empty list.", image.getConfig())); + } return CompletableFuture.completedFuture(Collections.emptyList()); } - - Slog.d(TAG, "Screenshot from user profile: " + userHandle.getIdentifier()); CompletableFuture<List<Notification.Action>> smartActionsFuture; long startTimeMs = SystemClock.uptimeMillis(); try { @@ -83,7 +92,9 @@ public class ScreenshotSmartActions { } catch (Throwable e) { long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs; smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList()); - Slog.e(TAG, "Failed to get future for screenshot notification smart actions.", e); + if (DEBUG_ACTIONS) { + Log.e(TAG, "Failed to get future for screenshot notification smart actions.", e); + } notifyScreenshotOp(screenshotId, smartActionsProvider, ScreenshotNotificationSmartActionsProvider.ScreenshotOp.REQUEST_SMART_ACTIONS, ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR, @@ -97,12 +108,18 @@ public class ScreenshotSmartActions { CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs, ScreenshotNotificationSmartActionsProvider smartActionsProvider) { long startTimeMs = SystemClock.uptimeMillis(); + if (DEBUG_ACTIONS) { + Log.d(TAG, String.format("getSmartActions id=%s, timeoutMs=%d, provider=%s", + screenshotId, timeoutMs, smartActionsProvider.getClass())); + } try { List<Notification.Action> actions = smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS); long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs; - Slog.d(TAG, String.format("Got %d smart actions. Wait time: %d ms", - actions.size(), waitTimeMs)); + if (DEBUG_ACTIONS) { + Log.d(TAG, String.format("Got %d smart actions. Wait time: %d ms", + actions.size(), waitTimeMs)); + } notifyScreenshotOp(screenshotId, smartActionsProvider, ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS, ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS, @@ -110,8 +127,10 @@ public class ScreenshotSmartActions { return actions; } catch (Throwable e) { long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs; - Slog.e(TAG, String.format("Error getting smart actions. Wait time: %d ms", waitTimeMs), - e); + if (DEBUG_ACTIONS) { + Log.e(TAG, String.format("Error getting smart actions. Wait time: %d ms", + waitTimeMs), e); + } ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status = (e instanceof TimeoutException) ? ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT @@ -127,10 +146,14 @@ public class ScreenshotSmartActions { ScreenshotNotificationSmartActionsProvider smartActionsProvider, ScreenshotNotificationSmartActionsProvider.ScreenshotOp op, ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status, long durationMs) { + if (DEBUG_ACTIONS) { + Log.d(TAG, String.format("%s notifyOp: %s id=%s, status=%s, durationMs=%d", + smartActionsProvider.getClass(), op, screenshotId, status, durationMs)); + } try { smartActionsProvider.notifyOp(screenshotId, op, status, durationMs); } catch (Throwable e) { - Slog.e(TAG, "Error in notifyScreenshotOp: ", e); + Log.e(TAG, "Error in notifyScreenshotOp: ", e); } } @@ -140,9 +163,13 @@ public class ScreenshotSmartActions { ScreenshotNotificationSmartActionsProvider provider = SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider( context, THREAD_POOL_EXECUTOR, new Handler()); + if (DEBUG_ACTIONS) { + Log.e(TAG, String.format("%s notifyAction: %s id=%s, isSmartAction=%b", + provider.getClass(), action, screenshotId, isSmartAction)); + } provider.notifyAction(screenshotId, action, isSmartAction); } catch (Throwable e) { - Slog.e(TAG, "Error in notifyScreenshotAction: ", e); + Log.e(TAG, "Error in notifyScreenshotAction: ", e); } } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java index 3814bd2999e9..cce60f9c7c9d 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java @@ -18,6 +18,14 @@ package com.android.systemui.screenshot; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM; +import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS; +import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT; +import static com.android.systemui.screenshot.LogConfig.DEBUG_SCROLL; +import static com.android.systemui.screenshot.LogConfig.DEBUG_UI; +import static com.android.systemui.screenshot.LogConfig.DEBUG_WINDOW; +import static com.android.systemui.screenshot.LogConfig.logTag; + import static java.util.Objects.requireNonNull; import android.animation.Animator; @@ -75,7 +83,7 @@ import java.util.function.Consumer; public class ScreenshotView extends FrameLayout implements ViewTreeObserver.OnComputeInternalInsetsListener { - private static final String TAG = "ScreenshotView"; + private static final String TAG = logTag(ScreenshotView.class); private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133; private static final long SCREENSHOT_FLASH_OUT_DURATION_MS = 217; @@ -166,12 +174,18 @@ public class ScreenshotView extends FrameLayout implements * @param onClick the action to take when the chip is clicked. */ public void showScrollChip(Runnable onClick) { + if (DEBUG_SCROLL) { + Log.d(TAG, "Showing Scroll option"); + } mScrollChip.setVisibility(VISIBLE); - mScrollChip.setOnClickListener((v) -> - onClick.run() - // TODO Logging, store event consumer to a field - //onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SCROLL_TAPPED); - ); + mScrollChip.setOnClickListener((v) -> { + if (DEBUG_INPUT) { + Log.d(TAG, "scroll chip tapped"); + } + onClick.run(); + // TODO Logging, store event consumer to a field + //onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SCROLL_TAPPED); + }); } @Override // ViewTreeObserver.OnComputeInternalInsetsListener @@ -179,15 +193,13 @@ public class ScreenshotView extends FrameLayout implements inoutInfo.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); Region touchRegion = new Region(); - Rect screenshotRect = new Rect(); - mScreenshotPreview.getBoundsOnScreen(screenshotRect); - touchRegion.op(screenshotRect, Region.Op.UNION); - Rect actionsRect = new Rect(); - mActionsContainer.getBoundsOnScreen(actionsRect); - touchRegion.op(actionsRect, Region.Op.UNION); - Rect dismissRect = new Rect(); - mDismissButton.getBoundsOnScreen(dismissRect); - touchRegion.op(dismissRect, Region.Op.UNION); + final Rect tmpRect = new Rect(); + mScreenshotPreview.getBoundsOnScreen(tmpRect); + touchRegion.op(tmpRect, Region.Op.UNION); + mActionsContainer.getBoundsOnScreen(tmpRect); + touchRegion.op(tmpRect, Region.Op.UNION); + mDismissButton.getBoundsOnScreen(tmpRect); + touchRegion.op(tmpRect, Region.Op.UNION); if (QuickStepContract.isGesturalMode(mNavMode)) { // Receive touches in gesture insets such that they don't cause TOUCH_OUTSIDE @@ -362,7 +374,6 @@ public class ScreenshotView extends FrameLayout implements toCorner.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); mScreenshotPreview.setVisibility(View.VISIBLE); } }); @@ -380,8 +391,13 @@ public class ScreenshotView extends FrameLayout implements dropInAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); + if (DEBUG_ANIM) { + Log.d(TAG, "drop-in animation completed"); + } mDismissButton.setOnClickListener(view -> { + if (DEBUG_INPUT) { + Log.d(TAG, "dismiss button clicked"); + } mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL); animateDismissal(); }); @@ -497,7 +513,7 @@ public class ScreenshotView extends FrameLayout implements try { imageData.editAction.actionIntent.send(); } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Intent cancelled", e); + Log.e(TAG, "PendingIntent was cancelled", e); } mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); animateDismissal(); @@ -543,6 +559,9 @@ public class ScreenshotView extends FrameLayout implements } private void animateDismissal(Animator dismissAnimation) { + if (DEBUG_WINDOW) { + Log.d(TAG, "removing OnComputeInternalInsetsListener"); + } getViewTreeObserver().removeOnComputeInternalInsetsListener(this); mDismissAnimation = dismissAnimation; mDismissAnimation.addListener(new AnimatorListenerAdapter() { @@ -551,6 +570,9 @@ public class ScreenshotView extends FrameLayout implements @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); + if (DEBUG_ANIM) { + Log.d(TAG, "Cancelled dismiss animation"); + } mCancelled = true; } @@ -558,17 +580,33 @@ public class ScreenshotView extends FrameLayout implements public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if (!mCancelled) { + if (DEBUG_ANIM) { + Log.d(TAG, "after dismiss animation, calling onDismissRunnable.run()"); + } mOnDismissRunnable.run(); } } }); + if (DEBUG_ANIM) { + Log.d(TAG, "Starting dismiss animation"); + } mDismissAnimation.start(); } void reset() { + if (DEBUG_UI) { + Log.d(TAG, "reset screenshot view"); + } + if (mDismissAnimation != null && mDismissAnimation.isRunning()) { + if (DEBUG_ANIM) { + Log.d(TAG, "cancelling dismiss animation"); + } mDismissAnimation.cancel(); } + if (DEBUG_WINDOW) { + Log.d(TAG, "removing OnComputeInternalInsetsListener"); + } // Make sure we clean up the view tree observer getViewTreeObserver().removeOnComputeInternalInsetsListener(this); // Clear any references to the bitmap @@ -637,10 +675,9 @@ public class ScreenshotView extends FrameLayout implements BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bitmap); if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0 || bitmap.getHeight() == 0) { - Log.e(TAG, String.format( - "Can't create insetted drawable, using 0 insets " - + "bitmap and insets create degenerate region: %dx%d %s", - bitmap.getWidth(), bitmap.getHeight(), insets)); + Log.e(TAG, "Can't create inset drawable, using 0 insets bitmap and insets create " + + "degenerate region: " + bitmap.getWidth() + "x" + bitmap.getHeight() + " " + + bitmapDrawable); return bitmapDrawable; } @@ -689,12 +726,18 @@ public class ScreenshotView extends FrameLayout implements } else if (event.getActionMasked() == MotionEvent.ACTION_UP) { if (isPastDismissThreshold() && (mDismissAnimation == null || !mDismissAnimation.isRunning())) { + if (DEBUG_INPUT) { + Log.d(TAG, "dismiss triggered via swipe gesture"); + } mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SWIPE_DISMISSED); animateDismissal(createSwipeDismissAnimation()); return true; } else if (MathUtils.dist(mStartX, mStartY, event.getRawX(), event.getRawY()) > dpToPx(CLICK_MOVEMENT_THRESHOLD_DP)) { // if we've moved a non-negligible distance (but not past the threshold), + if (DEBUG_DISMISS) { + Log.d(TAG, "swipe gesture abandoned"); + } // start the return animation if ((mDismissAnimation == null || !mDismissAnimation.isRunning())) { createSwipeReturnAnimation().start(); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java index ea835fa94fe8..e159992bc9a5 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java @@ -16,6 +16,8 @@ package com.android.systemui.screenshot; +import static com.android.systemui.screenshot.LogConfig.DEBUG_SCROLL; + import static java.util.Objects.requireNonNull; import android.annotation.UiContext; @@ -49,10 +51,7 @@ public class ScrollCaptureClient { @VisibleForTesting static final int MATCH_ANY_TASK = ActivityTaskManager.INVALID_TASK_ID; - private static final String TAG = "ScrollCaptureClient"; - - /** Whether to log method names and arguments for most calls */ - private static final boolean DEBUG_TRACE = false; + private static final String TAG = LogConfig.logTag(ScrollCaptureClient.class); /** * A connection to a remote window. Starts a capture session. @@ -155,7 +154,7 @@ public class ScrollCaptureClient { */ public void request(int displayId, int taskId, Consumer<Connection> consumer) { try { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "requestScrollCapture(displayId=" + displayId + ", " + mHostWindowToken + ", taskId=" + taskId + ", consumer=" + consumer + ")"); } @@ -189,7 +188,7 @@ public class ScrollCaptureClient { @Override public void onConnected(IScrollCaptureConnection connection, Rect scrollBounds, Point positionInWindow) throws RemoteException { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "onConnected(connection=" + connection + ", scrollBounds=" + scrollBounds + ", positionInWindow=" + positionInWindow + ")"); } @@ -202,7 +201,7 @@ public class ScrollCaptureClient { @Override public void onUnavailable() throws RemoteException { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "onUnavailable"); } // The targeted app does not support scroll capture @@ -211,7 +210,7 @@ public class ScrollCaptureClient { @Override public void onCaptureStarted() { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "onCaptureStarted()"); } mSessionConsumer.accept(this); @@ -224,7 +223,7 @@ public class ScrollCaptureClient { if (frameNumber != ScrollCaptureViewSupport.NO_FRAME_PRODUCED) { image = mReader.acquireNextImage(); } - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "onCaptureBufferSent(frameNumber=" + frameNumber + ", contentArea=" + contentArea + ") image=" + image); } @@ -237,7 +236,7 @@ public class ScrollCaptureClient { @Override public void onConnectionClosed() { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "onConnectionClosed()"); } disconnect(); @@ -261,7 +260,7 @@ public class ScrollCaptureClient { // -> Error handling: BiConsumer<Session, Throwable> ? @Override public void start(int maxBufferCount, Consumer<Session> sessionConsumer) { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "start(maxBufferCount=" + maxBufferCount + ", sessionConsumer=" + sessionConsumer + ")"); } @@ -288,7 +287,7 @@ public class ScrollCaptureClient { @Override public void end(Runnable listener) { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "end(listener=" + listener + ")"); } if (mStarted) { @@ -319,7 +318,7 @@ public class ScrollCaptureClient { @Override public void requestTile(Rect contentRect, Consumer<CaptureResult> consumer) { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "requestTile(contentRect=" + contentRect + "consumer=" + consumer + ")"); } mRequestRect = new Rect(contentRect); @@ -337,7 +336,7 @@ public class ScrollCaptureClient { */ @Override public void binderDied() { - if (DEBUG_TRACE) { + if (DEBUG_SCROLL) { Log.d(TAG, "binderDied()"); } disconnect(); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java index f32529fdaf04..3ad922b57c7c 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java @@ -16,6 +16,7 @@ package com.android.systemui.screenshot; +import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS; import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT; import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_TYPE; import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID; @@ -26,7 +27,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; -import android.util.Slog; import javax.inject.Inject; @@ -48,7 +48,9 @@ public class SmartActionsReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT); String actionType = intent.getStringExtra(EXTRA_ACTION_TYPE); - Slog.d(TAG, "Executing smart action [" + actionType + "]:" + pendingIntent.getIntent()); + if (DEBUG_ACTIONS) { + Log.d(TAG, "Executing smart action [" + actionType + "]:" + pendingIntent.getIntent()); + } ActivityOptions opts = ActivityOptions.makeBasic(); try { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java index 4aaea8041abd..c2b20d37f3f3 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java @@ -20,6 +20,10 @@ import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS; import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_PROCESS_COMPLETE; import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_URI; +import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK; +import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS; +import static com.android.systemui.screenshot.LogConfig.DEBUG_SERVICE; +import static com.android.systemui.screenshot.LogConfig.logTag; import android.app.Service; import android.content.BroadcastReceiver; @@ -53,17 +57,21 @@ import java.util.function.Consumer; import javax.inject.Inject; public class TakeScreenshotService extends Service { - private static final String TAG = "TakeScreenshotService"; + private static final String TAG = logTag(TakeScreenshotService.class); private final ScreenshotController mScreenshot; private final UserManager mUserManager; private final UiEventLogger mUiEventLogger; private final ScreenshotNotificationsController mNotificationsController; private final Handler mHandler; + private final BroadcastReceiver mCloseSystemDialogs = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction()) && mScreenshot != null) { + if (DEBUG_DISMISS) { + Log.d(TAG, "Received ACTION_CLOSE_SYSTEM_DIALOGS"); + } mScreenshot.dismissScreenshot(false); } } @@ -73,6 +81,9 @@ public class TakeScreenshotService extends Service { public TakeScreenshotService(ScreenshotController screenshotController, UserManager userManager, UiEventLogger uiEventLogger, ScreenshotNotificationsController notificationsController) { + if (DEBUG_SERVICE) { + Log.d(TAG, "new " + this); + } mHandler = new Handler(Looper.getMainLooper(), this::handleMessage); mScreenshot = screenshotController; mUserManager = userManager; @@ -81,13 +92,27 @@ public class TakeScreenshotService extends Service { } @Override + public void onCreate() { + if (DEBUG_SERVICE) { + Log.d(TAG, "onCreate()"); + } + } + + @Override public IBinder onBind(@NonNull Intent intent) { registerReceiver(mCloseSystemDialogs, new IntentFilter(ACTION_CLOSE_SYSTEM_DIALOGS)); - return new Messenger(mHandler).getBinder(); + final Messenger m = new Messenger(mHandler); + if (DEBUG_SERVICE) { + Log.d(TAG, "onBind: returning connection: " + m); + } + return m.getBinder(); } @Override public boolean onUnbind(Intent intent) { + if (DEBUG_SERVICE) { + Log.d(TAG, "onUnbind"); + } if (mScreenshot != null) { mScreenshot.dismissScreenshot(true); } @@ -95,6 +120,14 @@ public class TakeScreenshotService extends Service { return false; } + @Override + public void onDestroy() { + super.onDestroy(); + if (DEBUG_SERVICE) { + Log.d(TAG, "onDestroy"); + } + } + /** Respond to incoming Message via Binder (Messenger) */ private boolean handleMessage(Message msg) { final Messenger replyTo = msg.replyTo; @@ -108,7 +141,13 @@ public class TakeScreenshotService extends Service { Log.w(TAG, "Skipping screenshot because storage is locked!"); mNotificationsController.notifyScreenshotError( R.string.screenshot_failed_to_save_user_locked_text); + if (DEBUG_CALLBACK) { + Log.d(TAG, "handleMessage: calling uriConsumer.accept(null)"); + } uriConsumer.accept(null); + if (DEBUG_CALLBACK) { + Log.d(TAG, "handleMessage: calling onComplete.run()"); + } onComplete.run(); return true; } @@ -120,12 +159,21 @@ public class TakeScreenshotService extends Service { switch (msg.what) { case WindowManager.TAKE_SCREENSHOT_FULLSCREEN: + if (DEBUG_SERVICE) { + Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_FULLSCREEN"); + } mScreenshot.takeScreenshotFullscreen(uriConsumer, onComplete); break; case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION: + if (DEBUG_SERVICE) { + Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_SELECTED_REGION"); + } mScreenshot.takeScreenshotPartial(uriConsumer, onComplete); break; case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE: + if (DEBUG_SERVICE) { + Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_PROVIDED_IMAGE"); + } Bitmap screenshot = BitmapUtil.bundleToHardwareBitmap( screenshotRequest.getBitmapBundle()); Rect screenBounds = screenshotRequest.getBoundsInScreen(); @@ -145,7 +193,9 @@ public class TakeScreenshotService extends Service { private void sendComplete(Messenger target) { try { - Log.d(TAG, "sendComplete: " + target); + if (DEBUG_CALLBACK) { + Log.d(TAG, "sendComplete: " + target); + } target.send(Message.obtain(null, SCREENSHOT_MSG_PROCESS_COMPLETE)); } catch (RemoteException e) { Log.d(TAG, "ignored remote exception", e); @@ -154,7 +204,9 @@ public class TakeScreenshotService extends Service { private void reportUri(Messenger target, Uri uri) { try { - Log.d(TAG, "reportUri: " + target + " -> " + uri); + if (DEBUG_CALLBACK) { + Log.d(TAG, "reportUri: " + target + " -> " + uri); + } target.send(Message.obtain(null, SCREENSHOT_MSG_URI, uri)); } catch (RemoteException e) { Log.d(TAG, "ignored remote exception", e); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java index 721220729a33..d2c1bc10abb0 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationPromptController.java @@ -106,13 +106,16 @@ public class WindowMagnificationPromptController { final Notification.Builder notificationBuilder = new Notification.Builder(mContext, SystemNotificationChannels.ACCESSIBILITY_MAGNIFICATION); + final String message = mContext.getString(R.string.window_magnification_prompt_content); + notificationBuilder.setSmallIcon(R.drawable.ic_settings_24dp) .setContentTitle(mContext.getString(R.string.window_magnification_prompt_title)) - .setContentText(mContext.getString(R.string.window_magnification_prompt_content)) + .setContentText(message) .setLargeIcon(Icon.createWithResource(mContext, R.drawable.ic_accessibility_magnification)) .setTicker(mContext.getString(R.string.window_magnification_prompt_title)) .setOnlyAlertOnce(true) + .setStyle(new Notification.BigTextStyle().bigText(message)) .setDeleteIntent(createPendingIntent(ACTION_DISMISS)) .setContentIntent(createPendingIntent(ACTION_TURN_ON_IN_SETTINGS)) .setActions(buildTurnOnAction(), buildDismissAction()); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index da6e7ff84525..63128ced8f93 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -139,6 +139,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.Activity; +import android.app.ActivityClient; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManagerInternal; @@ -288,7 +289,6 @@ import android.util.SparseIntArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoUtils; -import android.view.Display; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -2859,12 +2859,13 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public final boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask) { - return mActivityTaskManager.finishActivity(token, resultCode, resultData, finishTask); + return ActivityClient.getInstance().finishActivity(token, resultCode, resultData, + finishTask); } @Override public void setRequestedOrientation(IBinder token, int requestedOrientation) { - mActivityTaskManager.setRequestedOrientation(token, requestedOrientation); + ActivityClient.getInstance().setRequestedOrientation(token, requestedOrientation); } @Override @@ -5711,7 +5712,7 @@ public class ActivityManagerService extends IActivityManager.Stub */ @Override public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) { - return mActivityTaskManager.moveActivityTaskToBack(token, nonRoot); + return ActivityClient.getInstance().moveActivityTaskToBack(token, nonRoot); } @Override @@ -5746,7 +5747,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public int getTaskForActivity(IBinder token, boolean onlyRoot) { - return mActivityTaskManager.getTaskForActivity(token, onlyRoot); + return ActivityClient.getInstance().getTaskForActivity(token, onlyRoot); } @Override @@ -6719,7 +6720,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean isTopOfTask(IBinder token) { - return mActivityTaskManager.isTopOfTask(token); + return ActivityClient.getInstance().isTopOfTask(token); } @Override @@ -16305,14 +16306,9 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public ActivityPresentationInfo getActivityPresentationInfo(IBinder token) { - int displayId = Display.INVALID_DISPLAY; - try { - displayId = mActivityTaskManager.getDisplayId(token); - } catch (RemoteException e) { - } - - return new ActivityPresentationInfo(mActivityTaskManager.getTaskForActivity(token, - /*onlyRoot=*/ false), displayId, + final ActivityClient ac = ActivityClient.getInstance(); + return new ActivityPresentationInfo(ac.getTaskForActivity(token, + /*onlyRoot=*/ false), ac.getDisplayId(token), mActivityTaskManager.getActivityClassForToken(token)); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ff05f121b97b..8fc9cb725859 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2211,22 +2211,27 @@ public class PackageManagerService extends IPackageManager.Stub res.removedInfo.sendPackageRemovedBroadcasts(killApp, false /*removedBySystem*/); } + final PermissionManagerServiceInternal.PackageInstalledParams.Builder + permissionParamsBuilder = + new PermissionManagerServiceInternal.PackageInstalledParams.Builder(); final List<String> grantedPermissionsList; if (grantPermissions) { if (grantedPermissions != null) { - grantedPermissionsList = Arrays.asList(grantedPermissions); + permissionParamsBuilder.setGrantedPermissions(Arrays.asList( + grantedPermissions)); } else { - grantedPermissionsList = res.pkg.getRequestedPermissions(); + permissionParamsBuilder.setGrantedPermissions( + res.pkg.getRequestedPermissions()); } - } else { - grantedPermissionsList = Collections.emptyList(); } - if (allowlistedRestrictedPermissions == null) { - allowlistedRestrictedPermissions = Collections.emptyList(); + if (allowlistedRestrictedPermissions != null) { + permissionParamsBuilder.setAllowlistedRestrictedPermissions( + allowlistedRestrictedPermissions); } + permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode); for (final int userId : res.newUsers) { - mPermissionManager.onPackageInstalled(res.pkg, grantedPermissionsList, - allowlistedRestrictedPermissions, autoRevokePermissionsMode, userId); + mPermissionManager.onPackageInstalled(res.pkg, permissionParamsBuilder.build(), + userId); } final String installerPackageName = @@ -3313,6 +3318,7 @@ public class PackageManagerService extends IPackageManager.Stub // Stub packages must either be replaced with full versions in the /data // partition or be disabled. final List<String> stubSystemApps = new ArrayList<>(); + final int[] userIds = mUserManager.getUserIds(); if (!mOnlyCore) { // do this first before mucking with mPackages for the "expecting better" case final int numPackages = mPackages.size(); @@ -3363,15 +3369,9 @@ public class PackageManagerService extends IPackageManager.Stub } if (!mSettings.isDisabledSystemPackageLPr(ps.name)) { - mSettings.mPackages.removeAt(index); logCriticalInfo(Log.WARN, "System package " + ps.name + " no longer exists; it's data will be wiped"); - - // Assume package is truly gone and wipe residual permissions. - mPermissionManager.updatePermissions(ps.name, null); - - // Actual deletion of code and data will be handled by later - // reconciliation step + removePackageDataLIF(ps, userIds, null, 0, false); } else { // we still have a disabled system package, but, it still might have // been removed. check the code path still exists and check there's @@ -3430,7 +3430,6 @@ public class PackageManagerService extends IPackageManager.Stub // Remove disable package settings for updated system apps that were // removed via an OTA. If the update is no longer present, remove the // app completely. Otherwise, revoke their system privileges. - final int[] userIds = mUserManager.getUserIds(); for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { final String packageName = possiblyDeletedUpdatedSystemApps.get(i); final AndroidPackage pkg = mPackages.get(packageName); @@ -3765,7 +3764,6 @@ public class PackageManagerService extends IPackageManager.Stub UserHandle.USER_SYSTEM).getLongVersionCode()); // Initialize InstantAppRegistry's Instant App list for all users. - final int[] userIds = UserManagerService.getInstance().getUserIds(); for (AndroidPackage pkg : mPackages.values()) { if (pkg.isSystem()) { continue; @@ -3931,7 +3929,12 @@ public class PackageManagerService extends IPackageManager.Stub } catch (PackageManagerException e) { Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); } - mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); + final int[] userIds = mUserManager.getUserIds(); + for (final int userId : userIds) { + mPermissionManager.onPackageInstalled(pkg, + PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, + userId); + } writeSettingsLPrTEMP(); } } catch (PackageManagerException e) { @@ -13673,14 +13676,16 @@ public class PackageManagerService extends IPackageManager.Stub if (installed) { if (pkgSetting.pkg != null) { + final PermissionManagerServiceInternal.PackageInstalledParams.Builder + permissionParamsBuilder = + new PermissionManagerServiceInternal.PackageInstalledParams.Builder(); if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) { - allowlistedRestrictedPermissions = pkgSetting.pkg.getRequestedPermissions(); - } else if (allowlistedRestrictedPermissions == null) { - allowlistedRestrictedPermissions = Collections.emptyList(); + permissionParamsBuilder.setAllowlistedRestrictedPermissions( + pkgSetting.pkg.getRequestedPermissions()); } - mPermissionManager.onPackageInstalled(pkgSetting.pkg, Collections.emptyList(), - allowlistedRestrictedPermissions, MODE_DEFAULT, userId); + mPermissionManager.onPackageInstalled(pkgSetting.pkg, + permissionParamsBuilder.build(), userId); } if (pkgSetting.pkg != null) { @@ -13939,7 +13944,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null) { - throw new IllegalArgumentException("Unknown target package: " + packageName); + return null; } final PackageUserState pus = ps.readUserState(userId); final Bundle allExtras = new Bundle(); @@ -16482,8 +16487,6 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath()); synchronized (mLock) { -// NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions - mPermissionManager.updatePermissions(pkgName, pkg); // For system-bundled packages, we assume that installing an upgraded version // of the package implies that the user actually wants to run that new code, // so we enable the package. @@ -19732,11 +19735,12 @@ public class PackageManagerService extends IPackageManager.Stub } } - // The update permissions method below will take care of removing obsolete permissions - // and granting install permissions. - mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); - if (applyUserRestrictions) { - for (int userId : allUserHandles) { + for (final int userId : allUserHandles) { + // The method below will take care of removing obsolete permissions and granting + // install permissions. + mPermissionManager.onPackageInstalled(pkg, + PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, userId); + if (applyUserRestrictions) { mSettings.writeRuntimePermissionsForUserLPr(userId, false); } } @@ -23581,7 +23585,7 @@ public class PackageManagerService extends IPackageManager.Stub // Note: this code block is executed with the Installer lock // already held, since it's invoked as a side-effect of // executeBatchLI() - if ((e != null) && pkg.isSystem()) { + if (e != null) { logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName + ", but trying to recover: " + e); destroyAppDataLeafLIF(pkg, userId, flags); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index e58d8c44ae8f..48e18f1b8b38 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -154,7 +154,6 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultBrowserProvider; import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultDialerProvider; import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultHomeProvider; -import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback; import com.android.server.policy.PermissionPolicyInternal; import com.android.server.policy.SoftRestrictedPermissionPolicy; @@ -4139,17 +4138,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { * * @param packageName The package that is updated * @param pkg The package that is updated, or {@code null} if package is deleted - * @param allPackages All currently known packages - * @param callback Callback to call after permission changes */ - private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg, - @NonNull PermissionCallback callback) { + private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) { // If the package is being deleted, update the permissions of all the apps final int flags = (pkg == null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG : UPDATE_PERMISSIONS_REPLACE_PKG); updatePermissions( - packageName, pkg, getVolumeUuidForPackage(pkg), flags, callback); + packageName, pkg, getVolumeUuidForPackage(pkg), flags, mDefaultPermissionCallback); } /** @@ -4947,17 +4943,19 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private void onPackageInstalledInternal(@NonNull AndroidPackage pkg, - @NonNull List<String> grantedPermissions, - @NonNull List<String> allowlistedRestrictedPermissions, int autoRevokePermissionsMode, + @NonNull PermissionManagerServiceInternal.PackageInstalledParams params, @UserIdInt int userId) { - addAllowlistedRestrictedPermissionsInternal(pkg, allowlistedRestrictedPermissions, + updatePermissions(pkg.getPackageName(), pkg); + addAllowlistedRestrictedPermissionsInternal(pkg, + params.getAllowlistedRestrictedPermissions(), FLAG_PERMISSION_WHITELIST_INSTALLER, userId); + final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode(); if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) { setAutoRevokeExemptedInternal(pkg, autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId); } - grantRequestedRuntimePermissionsInternal(pkg, grantedPermissions, userId); + grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId); } private void addAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg, @@ -4994,7 +4992,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { resetRuntimePermissionsInternal(pkg, userId); return; } - updatePermissions(packageName, null, mDefaultPermissionCallback); + updatePermissions(packageName, null); if (sharedUserPkgs.isEmpty()) { removeUidState(appId, userId); } else { @@ -5149,11 +5147,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { return PermissionManagerService.this.getAppOpPermissionPackagesInternal(permissionName); } @Override - public void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) { - PermissionManagerService.this - .updatePermissions(packageName, pkg, mDefaultPermissionCallback); - } - @Override public void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated) { PermissionManagerService.this .updateAllPermissions(volumeUuid, sdkUpdated, mDefaultPermissionCallback); @@ -5420,16 +5413,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override public void onPackageInstalled(@NonNull AndroidPackage pkg, - @NonNull List<String> grantedPermissions, - @NonNull List<String> allowlistedRestrictedPermissions, - int autoRevokePermissionsMode, @UserIdInt int userId) { + @NonNull PackageInstalledParams params, @UserIdInt int userId) { Objects.requireNonNull(pkg, "pkg"); - Objects.requireNonNull(grantedPermissions, "grantedPermissions"); - Objects.requireNonNull(allowlistedRestrictedPermissions, - "allowlistedRestrictedPermissions"); + Objects.requireNonNull(params, "params"); Preconditions.checkArgumentNonNegative(userId, "userId"); - onPackageInstalledInternal(pkg, grantedPermissions, allowlistedRestrictedPermissions, - autoRevokePermissionsMode, userId); + onPackageInstalledInternal(pkg, params, userId); } @Override @@ -5478,6 +5466,32 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } + /** + * Callbacks invoked when interesting actions have been taken on a permission. + * <p> + * NOTE: The current arguments are merely to support the existing use cases. This + * needs to be properly thought out with appropriate arguments for each of the + * callback methods. + */ + private static class PermissionCallback { + public void onGidsChanged(@AppIdInt int appId, @UserIdInt int userId) {} + public void onPermissionChanged() {} + public void onPermissionGranted(int uid, @UserIdInt int userId) {} + public void onInstallPermissionGranted() {} + public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {} + public void onInstallPermissionRevoked() {} + public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {} + public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync, + int uid) { + onPermissionUpdated(updatedUserIds, sync); + } + public void onPermissionRemoved() {} + public void onInstallPermissionUpdated() {} + public void onInstallPermissionUpdatedNotifyListener(int uid) { + onInstallPermissionUpdated(); + } + } + private static final class OnPermissionChangeListeners extends Handler { private static final int MSG_ON_PERMISSIONS_CHANGED = 1; diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java index 8ed7fb43fb81..f924651f1051 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java @@ -16,17 +16,19 @@ package com.android.server.pm.permission; -import android.annotation.AppIdInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.AppOpsManager; import android.content.pm.PermissionInfo; import android.permission.PermissionManagerInternal; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Consumer; @@ -140,41 +142,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager @NonNull Consumer<Boolean> callback); } - /** - * Callbacks invoked when interesting actions have been taken on a permission. - * <p> - * NOTE: The current arguments are merely to support the existing use cases. This - * needs to be properly thought out with appropriate arguments for each of the - * callback methods. - */ - public static class PermissionCallback { - public void onGidsChanged(@AppIdInt int appId, @UserIdInt int userId) { - } - public void onPermissionChanged() { - } - public void onPermissionGranted(int uid, @UserIdInt int userId) { - } - public void onInstallPermissionGranted() { - } - public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) { - } - public void onInstallPermissionRevoked() { - } - public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) { - } - public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync, - int uid) { - onPermissionUpdated(updatedUserIds, sync); - } - public void onPermissionRemoved() { - } - public void onInstallPermissionUpdated() { - } - public void onInstallPermissionUpdatedNotifyListener(int uid) { - onInstallPermissionUpdated(); - } - } - public abstract void systemReady(); /** @@ -189,22 +156,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager @UserIdInt int userId); /** - * Update permissions when a package changed. - * - * <p><ol> - * <li>Reconsider the ownership of permission</li> - * <li>Update the state (grant, flags) of the permissions</li> - * </ol> - * - * @param packageName The package that is updated - * @param pkg The package that is updated, or {@code null} if package is deleted - * @param allPackages All currently known packages - * @param callback Callback to call after permission changes - */ - public abstract void updatePermissions(@NonNull String packageName, - @Nullable AndroidPackage pkg); - - /** * Update all permissions for all apps. * * <p><ol> @@ -489,19 +440,15 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager @Nullable AndroidPackage oldPkg); /** - * Callback when a package has been installed for certain users. + * Callback when a package has been installed for a user. * * @param pkg the installed package - * @param grantedPermissions the permissions to be granted - * @param allowlistedRestrictedPermissions the restricted permissions to be allowlisted - * @param autoRevokePermissionsMode the auto revoke permissions mode for this package + * @param params the parameters passed in for package installation * @param userId the user ID this package is installed for */ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) public abstract void onPackageInstalled(@NonNull AndroidPackage pkg, - @NonNull List<String> grantedPermissions, - @NonNull List<String> allowlistedRestrictedPermissions, - int autoRevokePermissionsMode, @UserIdInt int userId); + @NonNull PackageInstalledParams params, @UserIdInt int userId); /** * Callback when a package has been removed. @@ -537,4 +484,132 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * @return whether the permission can be propagated */ public abstract boolean canPropagatePermissionToInstantApp(@NonNull String permissionName); + + /** + * The permission-related parameters passed in for package installation. + * + * @see android.content.pm.PackageInstaller.SessionParams + */ + //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) + public static final class PackageInstalledParams { + /** + * A static instance whose parameters are all in their default state. + */ + public static final PackageInstalledParams DEFAULT = new Builder().build(); + + @NonNull + private final List<String> mGrantedPermissions; + @NonNull + private final List<String> mAllowlistedRestrictedPermissions; + @NonNull + private final int mAutoRevokePermissionsMode; + + private PackageInstalledParams(@NonNull List<String> grantedPermissions, + @NonNull List<String> allowlistedRestrictedPermissions, + int autoRevokePermissionsMode) { + mGrantedPermissions = grantedPermissions; + mAllowlistedRestrictedPermissions = allowlistedRestrictedPermissions; + mAutoRevokePermissionsMode = autoRevokePermissionsMode; + } + + /** + * Get the permissions to be granted. + * + * @return the permissions to be granted + */ + @NonNull + public List<String> getGrantedPermissions() { + return mGrantedPermissions; + } + + /** + * Get the restricted permissions to be allowlisted. + * + * @return the restricted permissions to be allowlisted + */ + @NonNull + public List<String> getAllowlistedRestrictedPermissions() { + return mAllowlistedRestrictedPermissions; + } + + /** + * Get the mode for auto revoking permissions. + * + * @return the mode for auto revoking permissions + */ + public int getAutoRevokePermissionsMode() { + return mAutoRevokePermissionsMode; + } + + /** + * Builder class for {@link PackageInstalledParams}. + */ + public static final class Builder { + @NonNull + private List<String> mGrantedPermissions = Collections.emptyList(); + @NonNull + private List<String> mAllowlistedRestrictedPermissions = Collections.emptyList(); + @NonNull + private int mAutoRevokePermissionsMode = AppOpsManager.MODE_DEFAULT; + + /** + * Set the permissions to be granted. + * + * @param grantedPermissions the permissions to be granted + * + * @see android.content.pm.PackageInstaller.SessionParams#setGrantedRuntimePermissions( + * java.lang.String[]) + */ + public void setGrantedPermissions(@NonNull List<String> grantedPermissions) { + Objects.requireNonNull(grantedPermissions); + mGrantedPermissions = new ArrayList<>(grantedPermissions); + } + + /** + * Set the restricted permissions to be allowlisted. + * <p> + * Permissions that are not restricted are ignored, so one can just pass in all + * requested permissions of a package to get all its restricted permissions allowlisted. + * + * @param allowlistedRestrictedPermissions the restricted permissions to be allowlisted + * + * @see android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) + */ + public void setAllowlistedRestrictedPermissions( + @NonNull List<String> allowlistedRestrictedPermissions) { + Objects.requireNonNull(mGrantedPermissions); + mAllowlistedRestrictedPermissions = new ArrayList<>( + allowlistedRestrictedPermissions); + } + + /** + * Set the mode for auto revoking permissions. + * <p> + * {@link AppOpsManager#MODE_ALLOWED} means the system is allowed to auto revoke + * permissions from this package, and {@link AppOpsManager#MODE_IGNORED} means this + * package should be ignored when auto revoking permissions. + * {@link AppOpsManager#MODE_DEFAULT} means no changes will be made to the auto revoke + * mode of this package. + * + * @param autoRevokePermissionsMode the mode for auto revoking permissions + * + * @see android.content.pm.PackageInstaller.SessionParams#setAutoRevokePermissionsMode( + * boolean) + */ + public void setAutoRevokePermissionsMode(int autoRevokePermissionsMode) { + mAutoRevokePermissionsMode = autoRevokePermissionsMode; + } + + /** + * Build a new instance of {@link PackageInstalledParams}. + * + * @return the {@link PackageInstalledParams} built + */ + @NonNull + public PackageInstalledParams build() { + return new PackageInstalledParams(mGrantedPermissions, + mAllowlistedRestrictedPermissions, mAutoRevokePermissionsMode); + } + } + } } diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java index 1883f4e4e86c..ccd4e0ffa3e7 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java @@ -29,6 +29,7 @@ import android.os.PowerSaveState; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.IndentingPrintWriter; import android.util.KeyValueListParser; import android.util.Slog; import android.view.accessibility.AccessibilityManager; @@ -1031,90 +1032,92 @@ public class BatterySaverPolicy extends ContentObserver { } public void dump(PrintWriter pw) { + final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); + synchronized (mLock) { - pw.println(); - mBatterySavingStats.dump(pw, ""); - - pw.println(); - pw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):"); - pw.println(" Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS); - pw.println(" value: " + mSettings); - pw.println(" Settings: " + mDeviceSpecificSettingsSource); - pw.println(" value: " + mDeviceSpecificSettings); - - pw.println(" Adaptive Settings: " + Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS); - pw.println(" value: " + mAdaptiveSettings); - pw.println(" Adaptive Device Specific Settings: " + ipw.println(); + mBatterySavingStats.dump(ipw); + + ipw.println(); + ipw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):"); + ipw.increaseIndent(); + ipw.println("Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS); + ipw.increaseIndent(); + ipw.println("value: " + mSettings); + ipw.decreaseIndent(); + ipw.println("Settings: " + mDeviceSpecificSettingsSource); + ipw.increaseIndent(); + ipw.println("value: " + mDeviceSpecificSettings); + ipw.decreaseIndent(); + + ipw.println("Adaptive Settings: " + Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS); + ipw.increaseIndent(); + ipw.println("value: " + mAdaptiveSettings); + ipw.decreaseIndent(); + ipw.println("Adaptive Device Specific Settings: " + Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS); - pw.println(" value: " + mAdaptiveDeviceSpecificSettings); + ipw.increaseIndent(); + ipw.println("value: " + mAdaptiveDeviceSpecificSettings); + ipw.decreaseIndent(); + + ipw.println("mAccessibilityEnabled=" + mAccessibilityEnabled.get()); + ipw.println("mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get()); + ipw.println("mPolicyLevel=" + mPolicyLevel); - pw.println(" mAccessibilityEnabled=" + mAccessibilityEnabled.get()); - pw.println(" mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get()); - pw.println(" mPolicyLevel=" + mPolicyLevel); + dumpPolicyLocked(ipw, "full", mFullPolicy); + dumpPolicyLocked(ipw, "default adaptive", mDefaultAdaptivePolicy); + dumpPolicyLocked(ipw, "current adaptive", mAdaptivePolicy); + dumpPolicyLocked(ipw, "effective", mEffectivePolicyRaw); - dumpPolicyLocked(pw, " ", "full", mFullPolicy); - dumpPolicyLocked(pw, " ", "default adaptive", mDefaultAdaptivePolicy); - dumpPolicyLocked(pw, " ", "current adaptive", mAdaptivePolicy); - dumpPolicyLocked(pw, " ", "effective", mEffectivePolicyRaw); + ipw.decreaseIndent(); } } - private void dumpPolicyLocked(PrintWriter pw, String indent, String label, Policy p) { + private void dumpPolicyLocked(IndentingPrintWriter pw, String label, Policy p) { pw.println(); - pw.print(indent); pw.println("Policy '" + label + "'"); - pw.print(indent); - pw.println(" " + KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled); - pw.print(indent); - pw.println(" " + KEY_VIBRATION_DISABLED + "=" + p.disableVibration); - pw.print(indent); - pw.println(" " + KEY_ANIMATION_DISABLED + "=" + p.disableAnimation); - pw.print(indent); - pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + p.deferFullBackup); - pw.print(indent); - pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + p.deferKeyValueBackup); - pw.print(indent); - pw.println(" " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !p.enableFirewall); - pw.print(indent); - pw.println(" " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !p.enableDataSaver); - pw.print(indent); - pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + p.disableLaunchBoost); - pw.println( - " " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + !p.enableAdjustBrightness); - pw.print(indent); - pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor); - pw.print(indent); - pw.println(" " + KEY_GPS_MODE + "=" + p.locationMode); - pw.print(indent); - pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby); - pw.print(indent); - pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck); - pw.println( - " " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + p.disableOptionalSensors); - pw.print(indent); - pw.println(" " + KEY_AOD_DISABLED + "=" + p.disableAod); - pw.print(indent); - pw.println(" " + KEY_SOUNDTRIGGER_DISABLED + "=" + p.disableSoundTrigger); - pw.print(indent); - pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + p.enableQuickDoze); - pw.print(indent); - pw.println(" " + KEY_ENABLE_NIGHT_MODE + "=" + p.enableNightMode); - - pw.print(" Interactive File values:\n"); - dumpMap(pw, " ", p.filesForInteractive); + pw.increaseIndent(); + pw.println(KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled); + pw.println(KEY_VIBRATION_DISABLED + "=" + p.disableVibration); + pw.println(KEY_ANIMATION_DISABLED + "=" + p.disableAnimation); + pw.println(KEY_FULLBACKUP_DEFERRED + "=" + p.deferFullBackup); + pw.println(KEY_KEYVALUE_DEFERRED + "=" + p.deferKeyValueBackup); + pw.println(KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !p.enableFirewall); + pw.println(KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !p.enableDataSaver); + pw.println(KEY_LAUNCH_BOOST_DISABLED + "=" + p.disableLaunchBoost); + pw.println(KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + !p.enableAdjustBrightness); + pw.println(KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor); + pw.println(KEY_GPS_MODE + "=" + p.locationMode); + pw.println(KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby); + pw.println(KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck); + pw.println(KEY_OPTIONAL_SENSORS_DISABLED + "=" + p.disableOptionalSensors); + pw.println(KEY_AOD_DISABLED + "=" + p.disableAod); + pw.println(KEY_SOUNDTRIGGER_DISABLED + "=" + p.disableSoundTrigger); + pw.println(KEY_QUICK_DOZE_ENABLED + "=" + p.enableQuickDoze); + pw.println(KEY_ENABLE_NIGHT_MODE + "=" + p.enableNightMode); + + pw.println("Interactive File values:"); + pw.increaseIndent(); + dumpMap(pw, p.filesForInteractive); + pw.decreaseIndent(); pw.println(); - pw.print(" Noninteractive File values:\n"); - dumpMap(pw, " ", p.filesForNoninteractive); + pw.println("Noninteractive File values:"); + pw.increaseIndent(); + dumpMap(pw, p.filesForNoninteractive); + pw.decreaseIndent(); + + // Decrease from indent right after "Policy" line + pw.decreaseIndent(); } - private void dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map) { + private void dumpMap(PrintWriter pw, ArrayMap<String, String> map) { if (map == null) { + pw.println("N/A"); return; } final int size = map.size(); for (int i = 0; i < size; i++) { - pw.print(prefix); pw.print(map.keyAt(i)); pw.print(": '"); pw.print(map.valueAt(i)); diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java index af14d84d12b8..21500f649099 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java @@ -34,6 +34,7 @@ import android.os.PowerManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -888,70 +889,75 @@ public class BatterySaverStateMachine { } public void dump(PrintWriter pw) { + final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); + + ipw.println(); + ipw.println("Battery saver state machine:"); + ipw.increaseIndent(); synchronized (mLock) { - pw.println(); - pw.println("Battery saver state machine:"); - - pw.print(" Enabled="); - pw.println(mBatterySaverController.isEnabled()); - pw.print(" full="); - pw.println(mBatterySaverController.isFullEnabled()); - pw.print(" adaptive="); - pw.print(mBatterySaverController.isAdaptiveEnabled()); + ipw.print("Enabled="); + ipw.println(mBatterySaverController.isEnabled()); + ipw.increaseIndent(); + ipw.print("full="); + ipw.println(mBatterySaverController.isFullEnabled()); + ipw.print("adaptive="); + ipw.print(mBatterySaverController.isAdaptiveEnabled()); if (mBatterySaverController.isAdaptiveEnabled()) { - pw.print(" (advertise="); - pw.print( + ipw.print(" (advertise="); + ipw.print( mBatterySaverController.getBatterySaverPolicy().shouldAdvertiseIsEnabled()); - pw.print(")"); + ipw.print(")"); } - pw.println(); - pw.print(" mState="); - pw.println(mState); - - pw.print(" mLastChangedIntReason="); - pw.println(mLastChangedIntReason); - pw.print(" mLastChangedStrReason="); - pw.println(mLastChangedStrReason); - - pw.print(" mBootCompleted="); - pw.println(mBootCompleted); - pw.print(" mSettingsLoaded="); - pw.println(mSettingsLoaded); - pw.print(" mBatteryStatusSet="); - pw.println(mBatteryStatusSet); - - pw.print(" mIsPowered="); - pw.println(mIsPowered); - pw.print(" mBatteryLevel="); - pw.println(mBatteryLevel); - pw.print(" mIsBatteryLevelLow="); - pw.println(mIsBatteryLevelLow); - - pw.print(" mSettingAutomaticBatterySaver="); - pw.println(mSettingAutomaticBatterySaver); - pw.print(" mSettingBatterySaverEnabled="); - pw.println(mSettingBatterySaverEnabled); - pw.print(" mSettingBatterySaverEnabledSticky="); - pw.println(mSettingBatterySaverEnabledSticky); - pw.print(" mSettingBatterySaverStickyAutoDisableEnabled="); - pw.println(mSettingBatterySaverStickyAutoDisableEnabled); - pw.print(" mSettingBatterySaverStickyAutoDisableThreshold="); - pw.println(mSettingBatterySaverStickyAutoDisableThreshold); - pw.print(" mSettingBatterySaverTriggerThreshold="); - pw.println(mSettingBatterySaverTriggerThreshold); - pw.print(" mBatterySaverStickyBehaviourDisabled="); - pw.println(mBatterySaverStickyBehaviourDisabled); - - pw.print(" mDynamicPowerSavingsDefaultDisableThreshold="); - pw.println(mDynamicPowerSavingsDefaultDisableThreshold); - pw.print(" mDynamicPowerSavingsDisableThreshold="); - pw.println(mDynamicPowerSavingsDisableThreshold); - pw.print(" mDynamicPowerSavingsEnableBatterySaver="); - pw.println(mDynamicPowerSavingsEnableBatterySaver); - - pw.print(" mLastAdaptiveBatterySaverChangedExternallyElapsed="); - pw.println(mLastAdaptiveBatterySaverChangedExternallyElapsed); + ipw.decreaseIndent(); + ipw.println(); + ipw.print("mState="); + ipw.println(mState); + + ipw.print("mLastChangedIntReason="); + ipw.println(mLastChangedIntReason); + ipw.print("mLastChangedStrReason="); + ipw.println(mLastChangedStrReason); + + ipw.print("mBootCompleted="); + ipw.println(mBootCompleted); + ipw.print("mSettingsLoaded="); + ipw.println(mSettingsLoaded); + ipw.print("mBatteryStatusSet="); + ipw.println(mBatteryStatusSet); + + ipw.print("mIsPowered="); + ipw.println(mIsPowered); + ipw.print("mBatteryLevel="); + ipw.println(mBatteryLevel); + ipw.print("mIsBatteryLevelLow="); + ipw.println(mIsBatteryLevelLow); + + ipw.print("mSettingAutomaticBatterySaver="); + ipw.println(mSettingAutomaticBatterySaver); + ipw.print("mSettingBatterySaverEnabled="); + ipw.println(mSettingBatterySaverEnabled); + ipw.print("mSettingBatterySaverEnabledSticky="); + ipw.println(mSettingBatterySaverEnabledSticky); + ipw.print("mSettingBatterySaverStickyAutoDisableEnabled="); + ipw.println(mSettingBatterySaverStickyAutoDisableEnabled); + ipw.print("mSettingBatterySaverStickyAutoDisableThreshold="); + ipw.println(mSettingBatterySaverStickyAutoDisableThreshold); + ipw.print("mSettingBatterySaverTriggerThreshold="); + ipw.println(mSettingBatterySaverTriggerThreshold); + ipw.print("mBatterySaverStickyBehaviourDisabled="); + ipw.println(mBatterySaverStickyBehaviourDisabled); + + ipw.print("mDynamicPowerSavingsDefaultDisableThreshold="); + ipw.println(mDynamicPowerSavingsDefaultDisableThreshold); + ipw.print("mDynamicPowerSavingsDisableThreshold="); + ipw.println(mDynamicPowerSavingsDisableThreshold); + ipw.print("mDynamicPowerSavingsEnableBatterySaver="); + ipw.println(mDynamicPowerSavingsEnableBatterySaver); + + ipw.print("mLastAdaptiveBatterySaverChangedExternallyElapsed="); + ipw.println(mLastAdaptiveBatterySaverChangedExternallyElapsed); } + ipw.decreaseIndent(); } public void dumpProto(ProtoOutputStream proto, long tag) { diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java index 05695d919910..a7be2677cf23 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java @@ -17,6 +17,7 @@ package com.android.server.power.batterysaver; import android.os.BatteryManagerInternal; import android.os.SystemClock; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; @@ -26,7 +27,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.EventLogTags; import com.android.server.LocalServices; -import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; @@ -391,18 +391,15 @@ public class BatterySavingStats { stat.endTime = 0; } - public void dump(PrintWriter pw, String indent) { - synchronized (mLock) { - pw.print(indent); - pw.println("Battery saving stats:"); - - indent = indent + " "; + public void dump(IndentingPrintWriter pw) { + pw.println("Battery saving stats:"); + pw.increaseIndent(); + synchronized (mLock) { final long now = System.currentTimeMillis(); final long nowElapsed = injectCurrentTime(); final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - pw.print(indent); pw.print("Battery Saver is currently: "); switch (BatterySaverState.fromIndex(mCurrentState)) { case BatterySaverState.OFF: @@ -416,9 +413,8 @@ public class BatterySavingStats { break; } + pw.increaseIndent(); if (mLastBatterySaverEnabledTime > 0) { - pw.print(indent); - pw.print(" "); pw.print("Last ON time: "); pw.print(sdf.format(new Date(now - nowElapsed + mLastBatterySaverEnabledTime))); pw.print(" "); @@ -427,8 +423,6 @@ public class BatterySavingStats { } if (mLastBatterySaverDisabledTime > 0) { - pw.print(indent); - pw.print(" "); pw.print("Last OFF time: "); pw.print(sdf.format(new Date(now - nowElapsed + mLastBatterySaverDisabledTime))); pw.print(" "); @@ -436,14 +430,10 @@ public class BatterySavingStats { pw.println(); } - pw.print(indent); - pw.print(" "); pw.print("Times full enabled: "); pw.println(mBatterySaverEnabledCount); if (mLastAdaptiveBatterySaverEnabledTime > 0) { - pw.print(indent); - pw.print(" "); pw.print("Last ADAPTIVE ON time: "); pw.print(sdf.format( new Date(now - nowElapsed + mLastAdaptiveBatterySaverEnabledTime))); @@ -452,8 +442,6 @@ public class BatterySavingStats { pw.println(); } if (mLastAdaptiveBatterySaverDisabledTime > 0) { - pw.print(indent); - pw.print(" "); pw.print("Last ADAPTIVE OFF time: "); pw.print(sdf.format( new Date(now - nowElapsed + mLastAdaptiveBatterySaverDisabledTime))); @@ -461,39 +449,36 @@ public class BatterySavingStats { TimeUtils.formatDuration(mLastAdaptiveBatterySaverDisabledTime, nowElapsed, pw); pw.println(); } - pw.print(indent); - pw.print(" "); pw.print("Times adaptive enabled: "); pw.println(mAdaptiveBatterySaverEnabledCount); + pw.decreaseIndent(); pw.println(); - pw.print(indent); pw.println("Drain stats:"); - pw.print(indent); pw.println(" Battery saver OFF ON"); - dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr", + dumpLineLocked(pw, InteractiveState.NON_INTERACTIVE, "NonIntr", DozeState.NOT_DOZING, "NonDoze"); - dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr", + dumpLineLocked(pw, InteractiveState.INTERACTIVE, " Intr", DozeState.NOT_DOZING, " "); - dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr", + dumpLineLocked(pw, InteractiveState.NON_INTERACTIVE, "NonIntr", DozeState.DEEP, "Deep "); - dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr", + dumpLineLocked(pw, InteractiveState.INTERACTIVE, " Intr", DozeState.DEEP, " "); - dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr", + dumpLineLocked(pw, InteractiveState.NON_INTERACTIVE, "NonIntr", DozeState.LIGHT, "Light "); - dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr", + dumpLineLocked(pw, InteractiveState.INTERACTIVE, " Intr", DozeState.LIGHT, " "); } + pw.decreaseIndent(); } - private void dumpLineLocked(PrintWriter pw, String indent, + private void dumpLineLocked(IndentingPrintWriter pw, int interactiveState, String interactiveLabel, int dozeState, String dozeLabel) { - pw.print(indent); pw.print(dozeLabel); pw.print(" "); pw.print(interactiveLabel); diff --git a/services/core/java/com/android/server/tv/TEST_MAPPING b/services/core/java/com/android/server/tv/TEST_MAPPING new file mode 100644 index 000000000000..f718f909fecb --- /dev/null +++ b/services/core/java/com/android/server/tv/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "cts/tests/tests/tv" + } + ] +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 510893b2940b..608012e4a310 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -768,6 +768,7 @@ public final class TvInputManagerService extends SystemService { SessionState sessionState = userState.sessionStateMap.remove(sessionToken); if (sessionState == null) { + Slog.e(TAG, "sessionState null, no more remove session action!"); return; } @@ -2525,8 +2526,16 @@ public final class TvInputManagerService extends SystemService { ClientState clientState = userState.clientStateMap.get(clientToken); if (clientState != null) { while (clientState.sessionTokens.size() > 0) { + IBinder sessionToken = clientState.sessionTokens.get(0); releaseSessionLocked( - clientState.sessionTokens.get(0), Process.SYSTEM_UID, userId); + sessionToken, Process.SYSTEM_UID, userId); + // the releaseSessionLocked function may return before the sessionToken + // is removed if the related sessionState is null. So need to check again + // to avoid death curculation. + if (clientState.sessionTokens.contains(sessionToken)) { + Slog.d(TAG, "remove sessionToken " + sessionToken + " for " + clientToken); + clientState.sessionTokens.remove(sessionToken); + } } } clientToken = null; diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java new file mode 100644 index 000000000000..9f1152c8e371 --- /dev/null +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -0,0 +1,1046 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.INVALID_DISPLAY; + +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IMMERSIVE; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; +import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH; +import static com.android.server.wm.ActivityTaskManagerService.enforceNotIsolatedCaller; +import static com.android.server.wm.Task.ActivityState.DESTROYED; +import static com.android.server.wm.Task.ActivityState.DESTROYING; + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.ActivityOptions; +import android.app.ActivityTaskManager; +import android.app.IActivityClientController; +import android.app.PictureInPictureParams; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.PersistableBundle; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.Trace; +import android.service.voice.VoiceInteractionManagerInternal; +import android.util.Slog; +import android.view.RemoteAnimationDefinition; + +import com.android.internal.app.AssistUtils; +import com.android.internal.protolog.common.ProtoLog; +import com.android.server.LocalServices; +import com.android.server.Watchdog; +import com.android.server.uri.NeededUriGrants; +import com.android.server.vr.VrManagerInternal; + +import java.util.Arrays; + +/** + * Server side implementation for the client activity to interact with system. + * + * @see android.app.ActivityClient + */ +class ActivityClientController extends IActivityClientController.Stub { + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityClientController" : TAG_ATM; + private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; + + private final ActivityTaskManagerService mService; + private final WindowManagerGlobalLock mGlobalLock; + private final ActivityTaskSupervisor mTaskSupervisor; + private final Context mContext; + + /** Wrapper around VoiceInteractionServiceManager. */ + private AssistUtils mAssistUtils; + + ActivityClientController(ActivityTaskManagerService service) { + mService = service; + mGlobalLock = service.mGlobalLock; + mTaskSupervisor = service.mTaskSupervisor; + mContext = service.mContext; + } + + void onSystemReady() { + mAssistUtils = new AssistUtils(mContext); + } + + @Override + public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle"); + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r == null) { + return; + } + mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */, + false /* processPausingActivities */, config); + if (stopProfiling && r.hasProcess()) { + r.app.clearProfilerIfNeeded(); + } + } + } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void activityResumed(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + synchronized (mGlobalLock) { + ActivityRecord.activityResumedLocked(token); + } + Binder.restoreCallingIdentity(origId); + } + + @Override + public void activityTopResumedStateLost() { + final long origId = Binder.clearCallingIdentity(); + synchronized (mGlobalLock) { + mTaskSupervisor.handleTopResumedStateReleased(false /* timeout */); + } + Binder.restoreCallingIdentity(origId); + } + + @Override + public void activityPaused(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + synchronized (mGlobalLock) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused"); + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r != null) { + r.activityPaused(false); + } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + } + Binder.restoreCallingIdentity(origId); + } + + @Override + public void activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState, + CharSequence description) { + if (DEBUG_ALL) Slog.v(TAG, "Activity stopped: token=" + token); + + // Refuse possible leaked file descriptors. + if (icicle != null && icicle.hasFileDescriptors()) { + throw new IllegalArgumentException("File descriptors passed in Bundle"); + } + + final long origId = Binder.clearCallingIdentity(); + + String restartingName = null; + int restartingUid = 0; + final ActivityRecord r; + synchronized (mGlobalLock) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped"); + r = ActivityRecord.isInStackLocked(token); + if (r != null) { + if (r.attachedToProcess() && r.isState(Task.ActivityState.RESTARTING_PROCESS)) { + // The activity was requested to restart from + // {@link #restartActivityProcessIfVisible}. + restartingName = r.app.mName; + restartingUid = r.app.mUid; + } + r.activityStopped(icicle, persistentState, description); + } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + } + + if (restartingName != null) { + // In order to let the foreground activity can be restarted with its saved state from + // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed + // until the activity reports stopped with the state. And the activity record will be + // kept because the record state is restarting, then the activity will be restarted + // immediately if it is still the top one. + mTaskSupervisor.removeRestartTimeouts(r); + mService.mAmInternal.killProcess(restartingName, restartingUid, + "restartActivityProcess"); + } + mService.mAmInternal.trimApplications(); + + Binder.restoreCallingIdentity(origId); + } + + @Override + public void activityDestroyed(IBinder token) { + if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token); + final long origId = Binder.clearCallingIdentity(); + synchronized (mGlobalLock) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed"); + try { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r != null) { + r.destroyed("activityDestroyed"); + } + } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + Binder.restoreCallingIdentity(origId); + } + } + } + + @Override + public void activityRelaunched(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + synchronized (mGlobalLock) { + mTaskSupervisor.activityRelaunchedLocked(token); + } + Binder.restoreCallingIdentity(origId); + } + + @Override + public void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration, + int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) { + ProtoLog.v(WM_DEBUG_CONFIGURATION, "Report configuration: %s %s %s", + token, Arrays.toString(horizontalSizeConfiguration), + Arrays.toString(verticalSizeConfigurations)); + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setSizeConfigurations(horizontalSizeConfiguration, verticalSizeConfigurations, + smallestSizeConfigurations); + } + } + } + + /** + * Attempts to move a task backwards in z-order (the order of activities within the task is + * unchanged). + * + * There are several possible results of this call: + * - if the task is locked, then we will show the lock toast. + * - if there is a task behind the provided task, then that task is made visible and resumed as + * this task is moved to the back. + * - otherwise, if there are no other tasks in the root task: + * - if this task is in the pinned mode, then we remove the task completely, which will + * have the effect of moving the task to the top or bottom of the fullscreen root task + * (depending on whether it is visible). + * - otherwise, we simply return home and hide this task. + * + * @param token A reference to the activity we wish to move. + * @param nonRoot If false then this only works if the activity is the root + * of a task; if true it will work for any activity in a task. + * @return Returns true if the move completed, false if not. + */ + @Override + public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) { + enforceNotIsolatedCaller("moveActivityTaskToBack"); + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot); + final Task task = mService.mRootWindowContainer.anyTaskForId(taskId); + if (task != null) { + return ActivityRecord.getStackLocked(token).moveTaskToBack(task); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + return false; + } + + @Override + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) { + synchronized (mGlobalLock) { + final ActivityRecord srec = ActivityRecord.forTokenLocked(token); + if (srec != null) { + return srec.getRootTask().shouldUpRecreateTaskLocked(srec, destAffinity); + } + } + return false; + } + + @Override + public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode, + Intent resultData) { + final ActivityRecord r; + synchronized (mGlobalLock) { + r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return false; + } + } + + // Carefully collect grants without holding lock. + final NeededUriGrants destGrants = mService.collectGrants(destIntent, r); + final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo); + + synchronized (mGlobalLock) { + return r.getRootTask().navigateUpTo( + r, destIntent, destGrants, resultCode, resultData, resultGrants); + } + } + + @Override + public boolean releaseActivityInstance(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null || !r.isDestroyable()) { + return false; + } + r.destroyImmediately("app-req"); + return r.isState(DESTROYING, DESTROYED); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + /** + * This is the internal entry point for handling Activity.finish(). + * + * @param token The Binder token referencing the Activity we want to finish. + * @param resultCode Result code, if any, from this Activity. + * @param resultData Result data (Intent), if any, from this Activity. + * @param finishTask Whether to finish the task associated with this Activity. + * @return Returns true if the activity successfully finished, or false if it is still running. + */ + @Override + public boolean finishActivity(IBinder token, int resultCode, Intent resultData, + int finishTask) { + // Refuse possible leaked file descriptors. + if (resultData != null && resultData.hasFileDescriptors()) { + throw new IllegalArgumentException("File descriptors passed in Intent"); + } + + final ActivityRecord r; + synchronized (mGlobalLock) { + r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return true; + } + } + + // Carefully collect grants without holding lock. + final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo); + + synchronized (mGlobalLock) { + // Check again in case activity was removed when collecting grants. + if (!r.isInHistory()) { + return true; + } + + // Keep track of the root activity of the task before we finish it. + final Task tr = r.getTask(); + final ActivityRecord rootR = tr.getRootActivity(); + if (rootR == null) { + Slog.w(TAG, "Finishing task with all activities already finished"); + } + // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can + // finish. + if (mService.getLockTaskController().activityBlockedFromFinish(r)) { + return false; + } + + // TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked + // We should consolidate. + if (mService.mController != null) { + // Find the first activity that is not finishing. + final ActivityRecord next = + r.getRootTask().topRunningActivity(token, INVALID_TASK_ID); + if (next != null) { + // ask watcher if this is allowed + boolean resumeOK = true; + try { + resumeOK = mService.mController.activityResuming(next.packageName); + } catch (RemoteException e) { + mService.mController = null; + Watchdog.getInstance().setActivityController(null); + } + + if (!resumeOK) { + Slog.i(TAG, "Not finishing activity because controller resumed"); + return false; + } + } + } + + // Note down that the process has finished an activity and is in background activity + // starts grace period. + if (r.app != null) { + r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis()); + } + + final long origId = Binder.clearCallingIdentity(); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity"); + try { + final boolean res; + final boolean finishWithRootActivity = + finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY; + if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY + || (finishWithRootActivity && r == rootR)) { + // If requested, remove the task that is associated to this activity only if it + // was the root activity in the task. The result code and data is ignored + // because we don't support returning them across task boundaries. Also, to + // keep backwards compatibility we remove the task from recents when finishing + // task with root activity. + mTaskSupervisor.removeTask(tr, false /*killProcess*/, + finishWithRootActivity, "finish-activity"); + res = true; + // Explicitly dismissing the activity so reset its relaunch flag. + r.mRelaunchReason = RELAUNCH_REASON_NONE; + } else { + r.finishIfPossible(resultCode, resultData, resultGrants, + "app-request", true /* oomAdj */); + res = r.finishing; + if (!res) { + Slog.i(TAG, "Failed to finish by app-request"); + } + } + return res; + } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + Binder.restoreCallingIdentity(origId); + } + } + } + + @Override + public boolean finishActivityAffinity(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return false; + } + + // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps + // can finish. + if (mService.getLockTaskController().activityBlockedFromFinish(r)) { + return false; + } + + r.getTask().forAllActivities(activity -> r.finishIfSameAffinity(activity), + r /* boundary */, true /* includeBoundary */, + true /* traverseTopToBottom */); + return true; + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void finishSubActivity(IBinder token, String resultWho, int requestCode) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) return; + + // TODO: This should probably only loop over the task since you need to be in the + // same task to return results. + r.getRootTask().forAllActivities(activity -> { + activity.finishIfSubActivity(r /* parent */, resultWho, requestCode); + }, true /* traverseTopToBottom */); + + mService.updateOomAdj(); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public boolean isTopOfTask(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + return r != null && r.getTask().getTopNonFinishingActivity() == r; + } + } + + @Override + public boolean willActivityBeVisible(IBinder token) { + synchronized (mGlobalLock) { + final Task rootTask = ActivityRecord.getStackLocked(token); + return rootTask != null && rootTask.willActivityBeVisible(token); + } + } + + @Override + public int getDisplayId(IBinder activityToken) { + synchronized (mGlobalLock) { + final Task rootTask = ActivityRecord.getStackLocked(activityToken); + if (rootTask != null) { + final int displayId = rootTask.getDisplayId(); + return displayId != INVALID_DISPLAY ? displayId : DEFAULT_DISPLAY; + } + return DEFAULT_DISPLAY; + } + } + + @Override + public int getTaskForActivity(IBinder token, boolean onlyRoot) { + synchronized (mGlobalLock) { + return ActivityRecord.getTaskForActivityLocked(token, onlyRoot); + } + } + + @Override + public ComponentName getCallingActivity(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = getCallingRecord(token); + return r != null ? r.intent.getComponent() : null; + } + } + + @Override + public String getCallingPackage(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = getCallingRecord(token); + return r != null ? r.info.packageName : null; + } + } + + private static ActivityRecord getCallingRecord(IBinder token) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + return r != null ? r.resultTo : null; + } + + @Override + public Bundle getActivityOptions(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return null; + } + final ActivityOptions activityOptions = r.takeOptionsLocked(true /* fromClient */); + return activityOptions != null ? activityOptions.toBundle() : null; + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void setRequestedOrientation(IBinder token, int requestedOrientation) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setRequestedOrientation(requestedOrientation); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public int getRequestedOrientation(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + return r != null + ? r.getRequestedOrientation() : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + } + } + + @Override + public boolean convertFromTranslucent(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + return r != null && r.setOccludesParent(true); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public boolean convertToTranslucent(IBinder token, Bundle options) { + final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options); + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return false; + } + final ActivityRecord under = r.getTask().getActivityBelow(r); + if (under != null) { + under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null; + } + return r.setOccludesParent(false); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public boolean isImmersive(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + throw new IllegalArgumentException(); + } + return r.immersive; + } + } + + @Override + public void setImmersive(IBinder token, boolean immersive) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + throw new IllegalArgumentException(); + } + r.immersive = immersive; + + // Update associated state if we're frontmost. + if (r.isFocusedActivityOnDisplay()) { + ProtoLog.d(WM_DEBUG_IMMERSIVE, "Frontmost changed immersion: %s", r); + mService.applyUpdateLockStateLocked(r); + } + } + } + + @Override + public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ensureValidPictureInPictureActivityParams( + "enterPictureInPictureMode", token, params); + return mService.enterPictureInPictureMode(r, params); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ensureValidPictureInPictureActivityParams( + "setPictureInPictureParams", token, params); + + // Only update the saved args from the args that are set. + r.setPictureInPictureParams(params); + if (r.inPinnedWindowingMode()) { + // If the activity is already in picture-in-picture, update the pinned task now + // if it is not already expanding to fullscreen. Otherwise, the arguments will + // be used the next time the activity enters PiP. + final Task rootTask = r.getRootTask(); + rootTask.setPictureInPictureAspectRatio( + r.pictureInPictureArgs.getAspectRatio()); + rootTask.setPictureInPictureActions(r.pictureInPictureArgs.getActions()); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + /** + * Checks the state of the system and the activity associated with the given {@param token} to + * verify that picture-in-picture is supported for that activity. + * + * @return the activity record for the given {@param token} if all the checks pass. + */ + private ActivityRecord ensureValidPictureInPictureActivityParams(String caller, + IBinder token, PictureInPictureParams params) { + if (!mService.mSupportsPictureInPicture) { + throw new IllegalStateException(caller + + ": Device doesn't support picture-in-picture mode."); + } + + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r == null) { + throw new IllegalStateException(caller + + ": Can't find activity for token=" + token); + } + + if (!r.supportsPictureInPicture()) { + throw new IllegalStateException(caller + + ": Current activity does not support picture-in-picture."); + } + + if (params.hasSetAspectRatio() + && !mService.mWindowManager.isValidPictureInPictureAspectRatio( + r.mDisplayContent, params.getAspectRatio())) { + final float minAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); + final float maxAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio); + throw new IllegalArgumentException(String.format(caller + + ": Aspect ratio is too extreme (must be between %f and %f).", + minAspectRatio, maxAspectRatio)); + } + + // Truncate the number of actions if necessary. + params.truncateActions(ActivityTaskManager.getMaxNumPictureInPictureActions(mContext)); + return r; + } + + @Override + public void toggleFreeformWindowingMode(IBinder token) { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r == null) { + throw new IllegalArgumentException( + "toggleFreeformWindowingMode: No activity record matching token=" + + token); + } + + final Task rootTask = r.getRootTask(); + if (rootTask == null) { + throw new IllegalStateException("toggleFreeformWindowingMode: the activity " + + "doesn't have a root task"); + } + + if (!rootTask.inFreeformWindowingMode() + && rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { + throw new IllegalStateException("toggleFreeformWindowingMode: You can only " + + "toggle between fullscreen and freeform."); + } + + if (rootTask.inFreeformWindowingMode()) { + rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + } else if (!mService.mSizeCompatFreeform && r.inSizeCompatMode()) { + throw new IllegalStateException("Size-compat windows are currently not" + + "freeform-enabled"); + } else if (rootTask.getParent().inFreeformWindowingMode()) { + // If the window is on a freeform display, set it to undefined. It will be + // resolved to freeform and it can adjust windowing mode when the display mode + // changes in runtime. + rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED); + } else { + rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public void startLockTaskModeByToken(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r != null) { + mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */); + } + } + } + + @Override + public void stopLockTaskModeByToken(IBinder token) { + mService.stopLockTaskModeInternal(token, false /* isSystemCaller */); + } + + @Override + public void showLockTaskEscapeMessage(IBinder token) { + synchronized (mGlobalLock) { + if (ActivityRecord.forTokenLocked(token) != null) { + mService.getLockTaskController().showLockTaskToast(); + } + } + } + + @Override + public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setTaskDescription(td); + } + } + } + + @Override + public boolean showAssistFromActivity(IBinder token, Bundle args) { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord caller = ActivityRecord.forTokenLocked(token); + final Task topRootTask = mService.getTopDisplayFocusedRootTask(); + final ActivityRecord top = topRootTask != null + ? topRootTask.getTopNonFinishingActivity() : null; + if (top != caller) { + Slog.w(TAG, "showAssistFromActivity failed: caller " + caller + + " is not current top " + top); + return false; + } + if (!top.nowVisible) { + Slog.w(TAG, "showAssistFromActivity failed: caller " + caller + + " is not visible"); + return false; + } + } + return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION, + null /* showCallback */, token); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public boolean isRootVoiceInteraction(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + return r != null && r.rootVoiceInteraction; + } + } + + @Override + public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) { + Slog.i(TAG, "Activity tried to startLocalVoiceInteraction"); + synchronized (mGlobalLock) { + final Task topRootTask = mService.getTopDisplayFocusedRootTask(); + final ActivityRecord activity = topRootTask != null + ? topRootTask.getTopNonFinishingActivity() : null; + if (ActivityRecord.forTokenLocked(callingActivity) != activity) { + throw new SecurityException("Only focused activity can call startVoiceInteraction"); + } + if (mService.mRunningVoice != null || activity.getTask().voiceSession != null + || activity.voiceSession != null) { + Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction"); + return; + } + if (activity.pendingVoiceInteractionStart) { + Slog.w(TAG, "Pending start of voice interaction already."); + return; + } + activity.pendingVoiceInteractionStart = true; + } + LocalServices.getService(VoiceInteractionManagerInternal.class) + .startLocalVoiceInteraction(callingActivity, options); + } + + @Override + public void stopLocalVoiceInteraction(IBinder callingActivity) { + LocalServices.getService(VoiceInteractionManagerInternal.class) + .stopLocalVoiceInteraction(callingActivity); + } + + @Override + public void setShowWhenLocked(IBinder token, boolean showWhenLocked) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setShowWhenLocked(showWhenLocked); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setInheritShowWhenLocked(inheritShowWhenLocked); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void setTurnScreenOn(IBinder token, boolean turnScreenOn) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setTurnScreenOn(turnScreenOn); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.reportFullyDrawnLocked(restoredFromBundle); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void overridePendingTransition(IBinder token, String packageName, + int enterAnim, int exitAnim) { + final long origId = Binder.clearCallingIdentity(); + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null && r.isState(Task.ActivityState.RESUMED, Task.ActivityState.PAUSING)) { + r.mDisplayContent.mAppTransition.overridePendingAppTransition( + packageName, enterAnim, exitAnim, null, null); + } + } + Binder.restoreCallingIdentity(origId); + } + + @Override + public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) { + mService.enforceSystemHasVrFeature(); + + final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class); + final ActivityRecord r; + synchronized (mGlobalLock) { + r = ActivityRecord.isInStackLocked(token); + } + if (r == null) { + throw new IllegalArgumentException(); + } + + final int err; + if ((err = vrService.hasVrPackage(packageName, r.mUserId)) != VrManagerInternal.NO_ERROR) { + return err; + } + + // Clear the binder calling uid since this path may call moveToTask(). + final long callingId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + r.requestedVrComponent = (enabled) ? packageName : null; + + // Update associated state if this activity is currently focused. + if (r.isFocusedActivityOnDisplay()) { + mService.applyUpdateVrModeLocked(r); + } + return 0; + } + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + + @Override + public void setDisablePreviewScreenshots(IBinder token, boolean disable) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.setDisablePreviewScreenshots(disable); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) { + mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, + "registerRemoteAnimations"); + definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid()); + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.registerRemoteAnimations(definition); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void unregisterRemoteAnimations(IBinder token) { + mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, + "unregisterRemoteAnimations"); + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + r.unregisterRemoteAnimations(); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void onBackPressedOnTaskRoot(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return; + } + if (mService.mWindowOrganizerController.mTaskOrganizerController + .handleInterceptBackPressedOnTaskRoot(r.getRootTask())) { + // This task is handled by a task organizer that has requested the back pressed + // callback. + } else { + moveActivityTaskToBack(token, false /* nonRoot */); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } +} diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 1b8cc082f598..2e55e92a4dcd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4032,7 +4032,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mDisplayContent != null) { mDisplayContent.setLayoutNeeded(); } - mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); + mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, this).sendToTarget(); } } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 3710120a7934..8298dfd85114 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -33,8 +33,6 @@ import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; -import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; @@ -62,7 +60,6 @@ import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIV import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL; import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS; import static android.provider.Settings.System.FONT_SCALE; -import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; @@ -95,15 +92,8 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.Scr import static com.android.server.am.EventLogTags.writeBootProgressEnableScreen; import static com.android.server.am.EventLogTags.writeConfigurationChanged; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_IMMERSIVE; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ROOT_TASK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT; @@ -121,8 +111,6 @@ import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_P import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_ONLY; import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS; -import static com.android.server.wm.Task.ActivityState.DESTROYED; -import static com.android.server.wm.Task.ActivityState.DESTROYING; import static com.android.server.wm.Task.REPARENT_KEEP_ROOT_TASK_AT_FRONT; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; @@ -132,7 +120,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; @@ -143,6 +130,7 @@ import android.app.AlertDialog; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.Dialog; +import android.app.IActivityClientController; import android.app.IActivityController; import android.app.IActivityTaskManager; import android.app.IApplicationThread; @@ -197,7 +185,6 @@ import android.os.IUserManager; import android.os.LocaleList; import android.os.Looper; import android.os.Message; -import android.os.PersistableBundle; import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.Process; @@ -237,7 +224,6 @@ import android.window.WindowContainerTransaction; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.AssistUtils; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.ProcessMap; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; @@ -249,8 +235,6 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FrameworkStatsLog; -import com.android.internal.util.function.pooled.PooledConsumer; -import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AttributeCache; import com.android.server.LocalServices; @@ -271,7 +255,6 @@ import com.android.server.pm.UserManagerService; import com.android.server.policy.PermissionPolicyInternal; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriGrantsManagerInternal; -import com.android.server.vr.VrManagerInternal; import java.io.BufferedReader; import java.io.File; @@ -308,11 +291,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM; static final String TAG_ROOT_TASK = TAG + POSTFIX_ROOT_TASK; static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; - private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE; - private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS; - private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; - private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; - private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; // How long we wait until we timeout on key dispatching during instrumentation. static final long INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS = 60 * 1000; @@ -385,6 +363,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ final Object mGlobalLockWithoutBoost = mGlobalLock; ActivityTaskSupervisor mTaskSupervisor; + ActivityClientController mActivityClientController; RootWindowContainer mRootWindowContainer; WindowManagerService mWindowManager; private UserManagerService mUserManager; @@ -418,9 +397,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** State of external calls telling us if the device is awake or asleep. */ private boolean mKeyguardShown = false; - // Wrapper around VoiceInteractionServiceManager - private AssistUtils mAssistUtils; - // VoiceInteraction session ID that changes for each new request except when // being called for multi-window assist in a single session. private int mViSessionId = 1000; @@ -763,10 +739,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final PackageManager pm = mContext.getPackageManager(); mHasHeavyWeightFeature = pm.hasSystemFeature(FEATURE_CANT_SAVE_STATE); mHasLeanbackFeature = pm.hasSystemFeature(FEATURE_LEANBACK); - mAssistUtils = new AssistUtils(mContext); mVrController.onSystemReady(); mRecentTasks.onSystemReadyLocked(); mTaskSupervisor.onSystemReady(); + mActivityClientController.onSystemReady(); mBlockActivityAfterHomeEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, BLOCK_ACTIVITY_STARTS_AFTER_HOME_FLAG, false); @@ -872,6 +848,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mCompatModePackages = new CompatModePackages(this, systemDir, mH); mPendingIntentController = intentController; mTaskSupervisor = createTaskSupervisor(); + mActivityClientController = new ActivityClientController(this); mTaskChangeNotificationController = new TaskChangeNotificationController(mGlobalLock, mTaskSupervisor, mH); @@ -1698,311 +1675,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mAmInternal.getActivityInfoForUser(aInfo, userId); } - /** - * This is the internal entry point for handling Activity.finish(). - * - * @param token The Binder token referencing the Activity we want to finish. - * @param resultCode Result code, if any, from this Activity. - * @param resultData Result data (Intent), if any, from this Activity. - * @param finishTask Whether to finish the task associated with this Activity. - * @return Returns true if the activity successfully finished, or false if it is still running. - */ - @Override - public final boolean finishActivity(IBinder token, int resultCode, Intent resultData, - int finishTask) { - // Refuse possible leaked file descriptors - if (resultData != null && resultData.hasFileDescriptors()) { - throw new IllegalArgumentException("File descriptors passed in Intent"); - } - - final ActivityRecord r; - synchronized (mGlobalLock) { - r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return true; - } - } - - // Carefully collect grants without holding lock - final NeededUriGrants resultGrants = collectGrants(resultData, r.resultTo); - - synchronized (mGlobalLock) { - // Sanity check in case activity was removed before entering global lock. - if (!r.isInHistory()) { - return true; - } - - // Keep track of the root activity of the task before we finish it - final Task tr = r.getTask(); - final ActivityRecord rootR = tr.getRootActivity(); - if (rootR == null) { - Slog.w(TAG, "Finishing task with all activities already finished"); - } - // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can - // finish. - if (getLockTaskController().activityBlockedFromFinish(r)) { - return false; - } - - // TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked - // We should consolidate. - if (mController != null) { - // Find the first activity that is not finishing. - final ActivityRecord next = - r.getRootTask().topRunningActivity(token, INVALID_TASK_ID); - if (next != null) { - // ask watcher if this is allowed - boolean resumeOK = true; - try { - resumeOK = mController.activityResuming(next.packageName); - } catch (RemoteException e) { - mController = null; - Watchdog.getInstance().setActivityController(null); - } - - if (!resumeOK) { - Slog.i(TAG, "Not finishing activity because controller resumed"); - return false; - } - } - } - - // note down that the process has finished an activity and is in background activity - // starts grace period - if (r.app != null) { - r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis()); - } - - final long origId = Binder.clearCallingIdentity(); - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity"); - try { - boolean res; - final boolean finishWithRootActivity = - finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY; - if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY - || (finishWithRootActivity && r == rootR)) { - // If requested, remove the task that is associated to this activity only if it - // was the root activity in the task. The result code and data is ignored - // because we don't support returning them across task boundaries. Also, to - // keep backwards compatibility we remove the task from recents when finishing - // task with root activity. - mTaskSupervisor.removeTask(tr, false /*killProcess*/, - finishWithRootActivity, "finish-activity"); - res = true; - // Explicitly dismissing the activity so reset its relaunch flag. - r.mRelaunchReason = RELAUNCH_REASON_NONE; - } else { - r.finishIfPossible(resultCode, resultData, resultGrants, - "app-request", true /* oomAdj */); - res = r.finishing; - if (!res) { - Slog.i(TAG, "Failed to finish by app-request"); - } - } - return res; - } finally { - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public boolean finishActivityAffinity(IBinder token) { - synchronized (mGlobalLock) { - final long origId = Binder.clearCallingIdentity(); - try { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return false; - } - - // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps - // can finish. - if (getLockTaskController().activityBlockedFromFinish(r)) { - return false; - } - - final PooledFunction p = PooledLambda.obtainFunction( - ActivityRecord::finishIfSameAffinity, r, - PooledLambda.__(ActivityRecord.class)); - r.getTask().forAllActivities( - p, r, true /*includeBoundary*/, true /*traverseTopToBottom*/); - p.recycle(); - - return true; - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle"); - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r == null) { - return; - } - mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */, - false /* processPausingActivities */, config); - if (stopProfiling && r.hasProcess()) { - r.app.clearProfilerIfNeeded(); - } - } - } finally { - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - Binder.restoreCallingIdentity(origId); - } - } - - @Override - public final void activityResumed(IBinder token) { - final long origId = Binder.clearCallingIdentity(); - synchronized (mGlobalLock) { - ActivityRecord.activityResumedLocked(token); - } - Binder.restoreCallingIdentity(origId); - } - - @Override - public final void activityTopResumedStateLost() { - final long origId = Binder.clearCallingIdentity(); - synchronized (mGlobalLock) { - mTaskSupervisor.handleTopResumedStateReleased(false /* timeout */); - } - Binder.restoreCallingIdentity(origId); - } - - @Override - public final void activityPaused(IBinder token) { - final long origId = Binder.clearCallingIdentity(); - synchronized (mGlobalLock) { - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused"); - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r != null) { - r.activityPaused(false); - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - } - Binder.restoreCallingIdentity(origId); - } - - @Override - public final void activityStopped(IBinder token, Bundle icicle, - PersistableBundle persistentState, CharSequence description) { - if (DEBUG_ALL) Slog.v(TAG, "Activity stopped: token=" + token); - - // Refuse possible leaked file descriptors - if (icicle != null && icicle.hasFileDescriptors()) { - throw new IllegalArgumentException("File descriptors passed in Bundle"); - } - - final long origId = Binder.clearCallingIdentity(); - - String restartingName = null; - int restartingUid = 0; - final ActivityRecord r; - synchronized (mGlobalLock) { - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped"); - r = ActivityRecord.isInStackLocked(token); - if (r != null) { - if (r.attachedToProcess() - && r.isState(Task.ActivityState.RESTARTING_PROCESS)) { - // The activity was requested to restart from - // {@link #restartActivityProcessIfVisible}. - restartingName = r.app.mName; - restartingUid = r.app.mUid; - } - r.activityStopped(icicle, persistentState, description); - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - } - - if (restartingName != null) { - // In order to let the foreground activity can be restarted with its saved state from - // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed - // until the activity reports stopped with the state. And the activity record will be - // kept because the record state is restarting, then the activity will be restarted - // immediately if it is still the top one. - mTaskSupervisor.removeRestartTimeouts(r); - mAmInternal.killProcess(restartingName, restartingUid, "restartActivityProcess"); - } - mAmInternal.trimApplications(); - - Binder.restoreCallingIdentity(origId); - } - - @Override - public final void activityDestroyed(IBinder token) { - if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token); - synchronized (mGlobalLock) { - final long origId = Binder.clearCallingIdentity(); - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed"); - try { - final ActivityRecord activity = ActivityRecord.forTokenLocked(token); - if (activity != null) { - activity.destroyed("activityDestroyed"); - } - } finally { - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public final void activityRelaunched(IBinder token) { - final long origId = Binder.clearCallingIdentity(); - synchronized (mGlobalLock) { - mTaskSupervisor.activityRelaunchedLocked(token); - } - Binder.restoreCallingIdentity(origId); - } - @Override - public void setRequestedOrientation(IBinder token, int requestedOrientation) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.setRequestedOrientation(requestedOrientation); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public int getRequestedOrientation(IBinder token) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - return (r != null) - ? r.getRequestedOrientation() : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - } - } - - @Override - public void setImmersive(IBinder token, boolean immersive) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - throw new IllegalArgumentException(); - } - r.immersive = immersive; - - // update associated state if we're frontmost - if (r.isFocusedActivityOnDisplay()) { - ProtoLog.d(WM_DEBUG_IMMERSIVE, "Frontmost changed immersion: %s", r); - applyUpdateLockStateLocked(r); - } - } + public IActivityClientController getActivityClientController() { + return mActivityClientController; } void applyUpdateLockStateLocked(ActivityRecord r) { @@ -2025,17 +1700,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public boolean isImmersive(IBinder token) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - throw new IllegalArgumentException(); - } - return r.immersive; - } - } - - @Override public boolean isTopActivityImmersive() { enforceNotIsolatedCaller("isTopActivityImmersive"); synchronized (mGlobalLock) { @@ -2050,27 +1714,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void overridePendingTransition(IBinder token, String packageName, - int enterAnim, int exitAnim) { - synchronized (mGlobalLock) { - ActivityRecord self = ActivityRecord.isInStackLocked(token); - if (self == null) { - return; - } - - final long origId = Binder.clearCallingIdentity(); - - if (self.isState( - Task.ActivityState.RESUMED, Task.ActivityState.PAUSING)) { - self.mDisplayContent.mAppTransition.overridePendingAppTransition( - packageName, enterAnim, exitAnim, null, null); - } - - Binder.restoreCallingIdentity(origId); - } - } - - @Override public int getFrontActivityScreenCompatMode() { enforceNotIsolatedCaller("getFrontActivityScreenCompatMode"); synchronized (mGlobalLock) { @@ -2125,77 +1768,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public boolean convertFromTranslucent(IBinder token) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return false; - } - return r.setOccludesParent(true); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - @Override - public boolean convertToTranslucent(IBinder token, Bundle options) { - SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options); - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return false; - } - final ActivityRecord under = r.getTask().getActivityBelow(r); - if (under != null) { - under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null; - } - return r.setOccludesParent(false); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - @Override - public void notifyActivityDrawn(IBinder token) { - if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token); - synchronized (mGlobalLock) { - ActivityRecord r = mRootWindowContainer.isInAnyTask(token); - if (r != null) { - r.getRootTask().notifyActivityDrawnLocked(r); - } - } - } - - @Override - public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - r.reportFullyDrawnLocked(restoredFromBundle); - } - } - - @Override - public int getDisplayId(IBinder activityToken) throws RemoteException { - synchronized (mGlobalLock) { - final Task stack = ActivityRecord.getStackLocked(activityToken); - if (stack != null) { - final int displayId = stack.getDisplayId(); - return displayId != INVALID_DISPLAY ? displayId : DEFAULT_DISPLAY; - } - return DEFAULT_DISPLAY; - } - } - - @Override public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException { enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_TASKS, "getFocusedRootTaskInfo()"); final long ident = Binder.clearCallingIdentity(); @@ -2312,75 +1884,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public boolean shouldUpRecreateTask(IBinder token, String destAffinity) { - synchronized (mGlobalLock) { - final ActivityRecord srec = ActivityRecord.forTokenLocked(token); - if (srec != null) { - return srec.getRootTask().shouldUpRecreateTaskLocked(srec, destAffinity); - } - } - return false; - } - - @Override - public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode, - Intent resultData) { - final ActivityRecord r; - synchronized (mGlobalLock) { - r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return false; - } - } - - // Carefully collect grants without holding lock - final NeededUriGrants destGrants = collectGrants(destIntent, r); - final NeededUriGrants resultGrants = collectGrants(resultData, r.resultTo); - - synchronized (mGlobalLock) { - return r.getRootTask().navigateUpTo( - r, destIntent, destGrants, resultCode, resultData, resultGrants); - } - } - - /** - * Attempts to move a task backwards in z-order (the order of activities within the task is - * unchanged). - * - * There are several possible results of this call: - * - if the task is locked, then we will show the lock toast - * - if there is a task behind the provided task, then that task is made visible and resumed as - * this task is moved to the back - * - otherwise, if there are no other tasks in the stack: - * - if this task is in the pinned stack, then we remove the stack completely, which will - * have the effect of moving the task to the top or bottom of the fullscreen stack - * (depending on whether it is visible) - * - otherwise, we simply return home and hide this task - * - * @param token A reference to the activity we wish to move - * @param nonRoot If false then this only works if the activity is the root - * of a task; if true it will work for any activity in a task. - * @return Returns true if the move completed, false if not. - */ - @Override - public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) { - enforceNotIsolatedCaller("moveActivityTaskToBack"); - synchronized (mGlobalLock) { - final long origId = Binder.clearCallingIdentity(); - try { - int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot); - final Task task = mRootWindowContainer.anyTaskForId(taskId); - if (task != null) { - return ActivityRecord.getStackLocked(token).moveTaskToBack(task); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - return false; - } - - @Override public Rect getTaskBounds(int taskId) { enforceTaskPermission("getTaskBounds()"); final long ident = Binder.clearCallingIdentity(); @@ -2467,31 +1970,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public String getCallingPackage(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = getCallingRecordLocked(token); - return r != null ? r.info.packageName : null; - } - } - - @Override - public ComponentName getCallingActivity(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = getCallingRecordLocked(token); - return r != null ? r.intent.getComponent() : null; - } - } - - private ActivityRecord getCallingRecordLocked(IBinder token) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return null; - } - return r.resultTo; - } - - private NeededUriGrants collectGrants(Intent intent, ActivityRecord target) { + NeededUriGrants collectGrants(Intent intent, ActivityRecord target) { if (target != null) { return mUgmInternal.checkGrantUriPermissionFromIntent(intent, Binder.getCallingUid(), target.packageName, target.mUserId); @@ -2518,25 +1997,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public void onBackPressedOnTaskRoot(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - Task stack = r.getRootTask(); - final TaskOrganizerController taskOrgController = - mWindowOrganizerController.mTaskOrganizerController; - if (taskOrgController.handleInterceptBackPressedOnTaskRoot(stack)) { - // This task is handled by a task organizer that has requested the back pressed - // callback - } else { - moveActivityTaskToBack(token, false /* nonRoot */); - } - } - } - /** * TODO: Add mController hook */ @@ -2731,13 +2191,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public int getTaskForActivity(IBinder token, boolean onlyRoot) { - synchronized (mGlobalLock) { - return ActivityRecord.getTaskForActivityLocked(token, onlyRoot); - } - } - List<ActivityManager.RunningTaskInfo> getTasks(int maxNum) { return getTasks(maxNum, false /* filterForVisibleRecents */); } @@ -2772,40 +2225,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public final void finishSubActivity(IBinder token, String resultWho, int requestCode) { - synchronized (mGlobalLock) { - final long origId = Binder.clearCallingIdentity(); - try { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) return; - - final PooledConsumer c = PooledLambda.obtainConsumer( - ActivityRecord::finishIfSubActivity, PooledLambda.__(ActivityRecord.class), - r, resultWho, requestCode); - // TODO: This should probably only loop over the task since you need to be in the - // same task to return results. - r.getRootTask().forAllActivities(c); - c.recycle(); - - updateOomAdj(); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public boolean willActivityBeVisible(IBinder token) { - synchronized (mGlobalLock) { - Task stack = ActivityRecord.getStackLocked(token); - if (stack != null) { - return stack.willActivityBeVisible(token); - } - return false; - } - } - - @Override public void moveTaskToRootTask(int taskId, int rootTaskId, boolean toTop) { enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_TASKS, "moveTaskToRootTask()"); synchronized (mGlobalLock) { @@ -3035,17 +2454,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void startLockTaskModeByToken(IBinder token) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r == null) { - return; - } - startLockTaskModeLocked(r.getTask(), false /* isSystemCaller */); - } - } - - @Override public void startSystemLockTaskMode(int taskId) { enforceTaskPermission("startSystemLockTaskMode"); // This makes inner call to look as if it was initiated by system. @@ -3060,18 +2468,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // When starting lock task mode the stack must be in front and focused task.getRootTask().moveToFront("startSystemLockTaskMode"); - startLockTaskModeLocked(task, true /* isSystemCaller */); + startLockTaskMode(task, true /* isSystemCaller */); } } finally { Binder.restoreCallingIdentity(ident); } } - @Override - public void stopLockTaskModeByToken(IBinder token) { - stopLockTaskModeInternal(token, false /* isSystemCaller */); - } - /** * This API should be called by SystemUI only when user perform certain action to dismiss * lock task mode. We should only dismiss pinned lock task mode in this case. @@ -3082,8 +2485,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { stopLockTaskModeInternal(null, true /* isSystemCaller */); } - private void startLockTaskModeLocked(@Nullable Task task, boolean isSystemCaller) { - ProtoLog.w(WM_DEBUG_LOCKTASK, "startLockTaskModeLocked: %s", task); + void startLockTaskMode(@Nullable Task task, boolean isSystemCaller) { + ProtoLog.w(WM_DEBUG_LOCKTASK, "startLockTaskMode: %s", task); if (task == null || task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { return; } @@ -3111,7 +2514,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - private void stopLockTaskModeInternal(@Nullable IBinder token, boolean isSystemCaller) { + void stopLockTaskModeInternal(@Nullable IBinder token, boolean isSystemCaller) { final int callingUid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { @@ -3163,34 +2566,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r != null) { - r.setTaskDescription(td); - } - } - } - - @Override - public Bundle getActivityOptions(IBinder token) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r != null) { - final ActivityOptions activityOptions = r.takeOptionsLocked( - true /* fromClient */); - return activityOptions == null ? null : activityOptions.toBundle(); - } - return null; - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - @Override public List<IBinder> getAppTasks(String callingPackage) { int callingUid = Binder.getCallingUid(); assertPackageMatchesCallingUid(callingPackage); @@ -3220,39 +2595,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public boolean isTopOfTask(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - return r != null && r.getTask().getTopNonFinishingActivity() == r; - } - } - - @Override - public void notifyLaunchTaskBehindComplete(IBinder token) { - mTaskSupervisor.scheduleLaunchTaskBehindComplete(token); - } - - @Override - public void notifyEnterAnimationComplete(IBinder token) { - mH.post(() -> { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r != null && r.attachedToProcess()) { - try { - r.app.getThread().scheduleEnterAnimationComplete(r.appToken); - } catch (RemoteException e) { - } - } - } - - }); - } - - /** Called from an app when assist data is ready. */ - @Override - public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure, - AssistContent content, Uri referrer) { - PendingAssistExtras pae = (PendingAssistExtras) token; + public void reportAssistContextExtras(IBinder assistToken, Bundle extras, + AssistStructure structure, AssistContent content, Uri referrer) { + final PendingAssistExtras pae = (PendingAssistExtras) assistToken; synchronized (pae) { pae.result = extras; pae.structure = structure; @@ -3440,23 +2785,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public boolean releaseActivityInstance(IBinder token) { - synchronized (mGlobalLock) { - final long origId = Binder.clearCallingIdentity(); - try { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null || !r.isDestroyable()) { - return false; - } - r.destroyImmediately("app-req"); - return r.isState(DESTROYING, DESTROYED); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override public void releaseSomeActivities(IApplicationThread appInt) { synchronized (mGlobalLock) { final long origId = Binder.clearCallingIdentity(); @@ -3540,49 +2868,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public void toggleFreeformWindowingMode(IBinder token) { - synchronized (mGlobalLock) { - final long ident = Binder.clearCallingIdentity(); - try { - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r == null) { - throw new IllegalArgumentException( - "toggleFreeformWindowingMode: No activity record matching token=" - + token); - } - - final Task stack = r.getRootTask(); - if (stack == null) { - throw new IllegalStateException("toggleFreeformWindowingMode: the activity " - + "doesn't have a stack"); - } - - if (!stack.inFreeformWindowingMode() - && stack.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { - throw new IllegalStateException("toggleFreeformWindowingMode: You can only " - + "toggle between fullscreen and freeform."); - } - - if (stack.inFreeformWindowingMode()) { - stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); - } else if (!mSizeCompatFreeform && r.inSizeCompatMode()) { - throw new IllegalStateException("Size-compat windows are currently not" - + "freeform-enabled"); - } else if (stack.getParent().inFreeformWindowingMode()) { - // If the window is on a freeform display, set it to undefined. It will be - // resolved to freeform and it can adjust windowing mode when the display mode - // changes in runtime. - stack.setWindowingMode(WINDOWING_MODE_UNDEFINED); - } else { - stack.setWindowingMode(WINDOWING_MODE_FREEFORM); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - /** Sets the task stack listener that gets callbacks when a task stack changes. */ @Override public void registerTaskStackListener(ITaskStackListener listener) { @@ -3884,42 +3169,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return DevicePolicyCache.getInstance().isScreenCaptureAllowed(userId, false); } - @Override - public boolean showAssistFromActivity(IBinder token, Bundle args) { - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - ActivityRecord caller = ActivityRecord.forTokenLocked(token); - ActivityRecord top = getTopDisplayFocusedRootTask().getTopNonFinishingActivity(); - if (top != caller) { - Slog.w(TAG, "showAssistFromActivity failed: caller " + caller - + " is not current top " + top); - return false; - } - if (!top.nowVisible) { - Slog.w(TAG, "showAssistFromActivity failed: caller " + caller - + " is not visible"); - return false; - } - } - return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION, null, - token); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override - public boolean isRootVoiceInteraction(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return false; - } - return r.rootVoiceInteraction; - } - } - private void onLocalVoiceInteractionStartedLocked(IBinder activity, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) { ActivityRecord activityToCallback = ActivityRecord.forTokenLocked(activity); @@ -4001,17 +3250,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void showLockTaskEscapeMessage(IBinder token) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r == null) { - return; - } - getLockTaskController().showLockTaskToast(); - } - } - - @Override public void keyguardGoingAway(int flags) { enforceNotIsolatedCaller("keyguardGoingAway"); final long token = Binder.clearCallingIdentity(); @@ -4025,22 +3263,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration, - int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) { - ProtoLog.v(WM_DEBUG_CONFIGURATION, "Report configuration: %s %s %s", - token, Arrays.toString(horizontalSizeConfiguration), - Arrays.toString(verticalSizeConfigurations)); - synchronized (mGlobalLock) { - ActivityRecord record = ActivityRecord.isInStackLocked(token); - if (record == null) { - return; - } - record.setSizeConfigurations(horizontalSizeConfiguration, - verticalSizeConfigurations, smallestSizeConfigurations); - } - } - - @Override public void suppressResizeConfigChanges(boolean suppress) throws RemoteException { mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_TASKS, "suppressResizeConfigChanges()"); @@ -4138,100 +3360,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return true; } - @Override - public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked( - "enterPictureInPictureMode", token, params); - return enterPictureInPictureMode(r, params); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - @Override - public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked( - "setPictureInPictureParams", token, params); - - // Only update the saved args from the args that are set - r.setPictureInPictureParams(params); - if (r.inPinnedWindowingMode()) { - // If the activity is already in picture-in-picture, update the pinned stack now - // if it is not already expanding to fullscreen. Otherwise, the arguments will - // be used the next time the activity enters PiP - final Task stack = r.getRootTask(); - stack.setPictureInPictureAspectRatio( - r.pictureInPictureArgs.getAspectRatio()); - stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions()); - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - /** - * Checks the state of the system and the activity associated with the given {@param token} to - * verify that picture-in-picture is supported for that activity. - * - * @return the activity record for the given {@param token} if all the checks pass. - */ - private ActivityRecord ensureValidPictureInPictureActivityParamsLocked(String caller, - IBinder token, PictureInPictureParams params) { - if (!mSupportsPictureInPicture) { - throw new IllegalStateException(caller - + ": Device doesn't support picture-in-picture mode."); - } - - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r == null) { - throw new IllegalStateException(caller - + ": Can't find activity for token=" + token); - } - - if (!r.supportsPictureInPicture()) { - throw new IllegalStateException(caller - + ": Current activity does not support picture-in-picture."); - } - - if (params.hasSetAspectRatio() - && !mWindowManager.isValidPictureInPictureAspectRatio( - r.mDisplayContent, params.getAspectRatio())) { - final float minAspectRatio = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); - final float maxAspectRatio = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio); - throw new IllegalArgumentException(String.format(caller - + ": Aspect ratio is too extreme (must be between %f and %f).", - minAspectRatio, maxAspectRatio)); - } - - // Truncate the number of actions if necessary - params.truncateActions(ActivityTaskManager.getMaxNumPictureInPictureActions(mContext)); - - return r; - } - - @Override - public IBinder getUriPermissionOwnerForActivity(IBinder activityToken) { - enforceNotIsolatedCaller("getUriPermissionOwnerForActivity"); - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(activityToken); - if (r == null) { - throw new IllegalArgumentException("Activity does not exist; token=" - + activityToken); - } - return r.getUriPermissionsLocked().getExternalToken(); - } - } - // TODO(b/149338177): remove when CTS no-longer requires it @Override public void resizePrimarySplitScreen(Rect dockedBounds, Rect tempDockedTaskBounds, @@ -4304,73 +3432,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) { - enforceSystemHasVrFeature(); - - final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class); - - ActivityRecord r; - synchronized (mGlobalLock) { - r = ActivityRecord.isInStackLocked(token); - } - - if (r == null) { - throw new IllegalArgumentException(); - } - - int err; - if ((err = vrService.hasVrPackage(packageName, r.mUserId)) != - VrManagerInternal.NO_ERROR) { - return err; - } - - // Clear the binder calling uid since this path may call moveToTask(). - final long callingId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - r.requestedVrComponent = (enabled) ? packageName : null; - - // Update associated state if this activity is currently focused - if (r.isFocusedActivityOnDisplay()) { - applyUpdateVrModeLocked(r); - } - return 0; - } - } finally { - Binder.restoreCallingIdentity(callingId); - } - } - - @Override - public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) { - Slog.i(TAG, "Activity tried to startLocalVoiceInteraction"); - synchronized (mGlobalLock) { - ActivityRecord activity = getTopDisplayFocusedRootTask().getTopNonFinishingActivity(); - if (ActivityRecord.forTokenLocked(callingActivity) != activity) { - throw new SecurityException("Only focused activity can call startVoiceInteraction"); - } - if (mRunningVoice != null || activity.getTask().voiceSession != null - || activity.voiceSession != null) { - Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction"); - return; - } - if (activity.pendingVoiceInteractionStart) { - Slog.w(TAG, "Pending start of voice interaction already."); - return; - } - activity.pendingVoiceInteractionStart = true; - } - LocalServices.getService(VoiceInteractionManagerInternal.class) - .startLocalVoiceInteraction(callingActivity, options); - } - - @Override - public void stopLocalVoiceInteraction(IBinder callingActivity) { - LocalServices.getService(VoiceInteractionManagerInternal.class) - .stopLocalVoiceInteraction(callingActivity); - } - - @Override public boolean supportsLocalVoiceInteraction() { return LocalServices.getService(VoiceInteractionManagerInternal.class) .supportsLocalVoiceInteraction(); @@ -4474,24 +3535,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void setDisablePreviewScreenshots(IBinder token, boolean disable) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - Slog.w(TAG, "setDisablePreviewScreenshots: Unable to find activity for token=" - + token); - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.setDisablePreviewScreenshots(disable); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override public void invalidateHomeTaskSnapshot(IBinder token) { synchronized (mGlobalLock) { final ActivityRecord r = ActivityRecord.isInStackLocked(token); @@ -4532,91 +3575,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void setShowWhenLocked(IBinder token, boolean showWhenLocked) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.setShowWhenLocked(showWhenLocked); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.setInheritShowWhenLocked(inheritShowWhenLocked); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public void setTurnScreenOn(IBinder token, boolean turnScreenOn) { - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.setTurnScreenOn(turnScreenOn); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) { - mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, - "registerRemoteAnimations"); - definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid()); - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.registerRemoteAnimations(definition); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override - public void unregisterRemoteAnimations(IBinder token) { - mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, - "unregisterRemoteAnimations"); - synchronized (mGlobalLock) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - try { - r.unregisterRemoteAnimations(); - } finally { - Binder.restoreCallingIdentity(origId); - } - } - } - - @Override public void registerRemoteAnimationForNextActivityStart(String packageName, RemoteAnimationAdapter adapter) { mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, @@ -4743,7 +3701,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mVrController.shouldDisableNonVrUiLocked(); } - private void applyUpdateVrModeLocked(ActivityRecord r) { + void applyUpdateVrModeLocked(ActivityRecord r) { // VR apps are expected to run in a main display. If an app is turning on VR for // itself, but isn't on the main display, then move it there before enabling VR Mode. if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) { @@ -5097,7 +4055,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mAmInternal.getCurrentUserId(); } - private void enforceNotIsolatedCaller(String caller) { + static void enforceNotIsolatedCaller(String caller) { if (UserHandle.isIsolated(Binder.getCallingUid())) { throw new SecurityException("Isolated process not allowed to call " + caller); } diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index a4ac16f2ec77..cd3f32278165 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -307,6 +307,11 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { return this; } + /** Cheap way of doing cast and instanceof. */ + DisplayArea.Tokens asTokens() { + return null; + } + @Override void forAllDisplayAreas(Consumer<DisplayArea> callback) { super.forAllDisplayAreas(callback); @@ -544,6 +549,11 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { mLastOrientationSource = win; return req; } + + @Override + final DisplayArea.Tokens asTokens() { + return this; + } } @Override diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index 211bd5d9eb77..7573e92e82a8 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -86,7 +86,7 @@ public abstract class DisplayAreaPolicy { @Override public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, RootDisplayArea root, - DisplayArea<? extends WindowContainer> imeContainer) { + DisplayArea.Tokens imeContainer) { final TaskDisplayArea defaultTaskDisplayArea = new TaskDisplayArea(content, wmService, "DefaultTaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER); final List<TaskDisplayArea> tdaList = new ArrayList<>(); @@ -151,7 +151,7 @@ public abstract class DisplayAreaPolicy { * @see DisplayAreaPolicy#DisplayAreaPolicy */ DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, - RootDisplayArea root, DisplayArea<? extends WindowContainer> imeContainer); + RootDisplayArea root, DisplayArea.Tokens imeContainer); /** * Instantiates the device-specific {@link Provider}. diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java index 6a420874b924..bc3220673ed3 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java @@ -247,7 +247,7 @@ class DisplayAreaPolicyBuilder { private final ArrayList<DisplayAreaPolicyBuilder.Feature> mFeatures = new ArrayList<>(); private final ArrayList<TaskDisplayArea> mTaskDisplayAreas = new ArrayList<>(); @Nullable - private DisplayArea<? extends WindowContainer> mImeContainer; + private DisplayArea.Tokens mImeContainer; HierarchyBuilder(RootDisplayArea root) { mRoot = root; @@ -270,7 +270,7 @@ class DisplayAreaPolicyBuilder { } /** Sets IME container as a child of this hierarchy root. */ - HierarchyBuilder setImeContainer(DisplayArea<? extends WindowContainer> imeContainer) { + HierarchyBuilder setImeContainer(DisplayArea.Tokens imeContainer) { mImeContainer = imeContainer; return this; } @@ -706,6 +706,10 @@ class DisplayAreaPolicyBuilder { private DisplayArea createArea(DisplayArea<DisplayArea> parent, DisplayArea.Tokens[] areaForLayer) { if (mExisting != null) { + if (mExisting.asTokens() != null) { + // Store the WindowToken container for layers + fillAreaForLayers(mExisting.asTokens(), areaForLayer); + } return mExisting; } if (mSkipTokens) { @@ -722,14 +726,18 @@ class DisplayAreaPolicyBuilder { if (mFeature == null) { final DisplayArea.Tokens leaf = new DisplayArea.Tokens(parent.mWmService, type, "Leaf:" + mMinLayer + ":" + mMaxLayer); - for (int i = mMinLayer; i <= mMaxLayer; i++) { - areaForLayer[i] = leaf; - } + fillAreaForLayers(leaf, areaForLayer); return leaf; } else { return mFeature.mNewDisplayAreaSupplier.create(parent.mWmService, type, mFeature.mName + ":" + mMinLayer + ":" + mMaxLayer, mFeature.mId); } } + + private void fillAreaForLayers(DisplayArea.Tokens leaf, DisplayArea.Tokens[] areaForLayer) { + for (int i = mMinLayer; i <= mMaxLayer; i++) { + areaForLayer[i] = leaf; + } + } } } diff --git a/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java b/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java index 14880ed30f24..9602880486b5 100644 --- a/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java +++ b/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import android.app.ActivityTaskManager; import android.app.UriGrantsManager; import android.content.ClipData; import android.net.Uri; @@ -33,6 +32,7 @@ import java.util.ArrayList; class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub implements IBinder.DeathRecipient { + private final WindowManagerGlobalLock mGlobalLock; private final int mSourceUid; private final String mTargetPackage; private final int mMode; @@ -45,8 +45,9 @@ class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub private IBinder mPermissionOwnerToken = null; private IBinder mTransientToken = null; - DragAndDropPermissionsHandler(ClipData clipData, int sourceUid, String targetPackage, int mode, - int sourceUserId, int targetUserId) { + DragAndDropPermissionsHandler(WindowManagerGlobalLock lock, ClipData clipData, int sourceUid, + String targetPackage, int mode, int sourceUserId, int targetUserId) { + mGlobalLock = lock; mSourceUid = sourceUid; mTargetPackage = targetPackage; mMode = mode; @@ -64,8 +65,7 @@ class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub mActivityToken = activityToken; // Will throw if Activity is not found. - IBinder permissionOwner = ActivityTaskManager.getService(). - getUriPermissionOwnerForActivity(mActivityToken); + IBinder permissionOwner = getUriPermissionOwnerForActivity(mActivityToken); doTake(permissionOwner); } @@ -105,8 +105,7 @@ class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub IBinder permissionOwner = null; if (mActivityToken != null) { try { - permissionOwner = ActivityTaskManager.getService(). - getUriPermissionOwnerForActivity(mActivityToken); + permissionOwner = getUriPermissionOwnerForActivity(mActivityToken); } catch (Exception e) { // Activity is destroyed, permissions already revoked. return; @@ -126,6 +125,18 @@ class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub } } + private IBinder getUriPermissionOwnerForActivity(IBinder activityToken) { + ActivityTaskManagerService.enforceNotIsolatedCaller("getUriPermissionOwnerForActivity"); + synchronized (mGlobalLock) { + ActivityRecord r = ActivityRecord.isInStackLocked(activityToken); + if (r == null) { + throw new IllegalArgumentException("Activity does not exist; token=" + + activityToken); + } + return r.getUriPermissionsLocked().getExternalToken(); + } + } + @Override public void binderDied() { try { diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index ad4e64a08183..86518ea4ccc1 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -59,7 +59,6 @@ import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; -import com.android.internal.os.SomeArgs; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.view.IDragAndDropPermissions; import com.android.server.LocalServices; @@ -590,7 +589,7 @@ class DragState { final DragAndDropPermissionsHandler dragAndDropPermissions; if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0 && mData != null) { - dragAndDropPermissions = new DragAndDropPermissionsHandler( + dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock, mData, mUid, touchedWin.getOwningPackage(), diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java index da04f438a496..c4fcea68a6fc 100644 --- a/services/core/java/com/android/server/wm/RootDisplayArea.java +++ b/services/core/java/com/android/server/wm/RootDisplayArea.java @@ -16,11 +16,17 @@ package com.android.server.wm; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER; import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER; import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; +import android.annotation.Nullable; + +import com.android.server.policy.WindowManagerPolicy; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -72,7 +78,8 @@ class RootDisplayArea extends DisplayArea<DisplayArea> { * match the root. */ void placeImeContainer(DisplayArea.Tokens imeContainer) { - if (imeContainer.getRootDisplayArea() == this) { + final RootDisplayArea previousRoot = imeContainer.getRootDisplayArea(); + if (previousRoot == this) { // No need to reparent if IME container is below the same root. return; } @@ -88,7 +95,9 @@ class RootDisplayArea extends DisplayArea<DisplayArea> { + "FEATURE_IME_PLACEHOLDER"); } + previousRoot.updateImeContainerForLayers(null /* imeContainer */); imeContainer.reparent(imeDisplayAreas.get(0), POSITION_TOP); + updateImeContainerForLayers(imeContainer); return; } } @@ -119,4 +128,10 @@ class RootDisplayArea extends DisplayArea<DisplayArea> { mAreaForLayer = areaForLayer; mFeatureToDisplayAreas = featureToDisplayAreas; } + + private void updateImeContainerForLayers(@Nullable DisplayArea.Tokens imeContainer) { + final WindowManagerPolicy policy = mWmService.mPolicy; + mAreaForLayer[policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD)] = imeContainer; + mAreaForLayer[policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD_DIALOG)] = imeContainer; + } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d4efa8a7ab91..7c290c465c32 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1121,10 +1121,7 @@ public class WindowManagerService extends IWindowManager.Stub final boolean isRecentsAnimationTarget = getRecentsAnimationController() != null && getRecentsAnimationController().isTargetApp(atoken); if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget) { - try { - mActivityTaskManager.notifyLaunchTaskBehindComplete(atoken.token); - } catch (RemoteException e) { - } + mAtmService.mTaskSupervisor.scheduleLaunchTaskBehindComplete(atoken.token); atoken.mLaunchTaskBehind = false; } else { atoken.updateReportedVisibilityLocked(); @@ -1132,9 +1129,11 @@ public class WindowManagerService extends IWindowManager.Stub // successfully finishes. if (atoken.mEnteringAnimation && !isRecentsAnimationTarget) { atoken.mEnteringAnimation = false; - try { - mActivityTaskManager.notifyEnterAnimationComplete(atoken.token); - } catch (RemoteException e) { + if (atoken != null && atoken.attachedToProcess()) { + try { + atoken.app.getThread().scheduleEnterAnimationComplete(atoken.appToken); + } catch (RemoteException e) { + } } } } @@ -5108,9 +5107,11 @@ public class WindowManagerService extends IWindowManager.Stub } case NOTIFY_ACTIVITY_DRAWN: { - try { - mActivityTaskManager.notifyActivityDrawn((IBinder) msg.obj); - } catch (RemoteException e) { + final ActivityRecord activity = (ActivityRecord) msg.obj; + synchronized (mGlobalLock) { + if (activity.isAttached()) { + activity.getRootTask().notifyActivityDrawnLocked(activity); + } } break; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 262328ca0f0a..513543e0aec8 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -218,8 +218,10 @@ import android.os.Process; import android.os.RecoverySystem; import android.os.RemoteCallback; import android.os.RemoteException; +import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceSpecificException; +import android.os.ShellCallback; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; @@ -8733,6 +8735,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { pw.decreaseIndent(); } + @Override + public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, + String[] args, ShellCallback callback, ResultReceiver resultReceiver) { + new DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService.this).exec( + this, in, out, err, args, callback, resultReceiver); + + } + private String getEncryptionStatusName(int encryptionStatus) { switch (encryptionStatus) { case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE: diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java new file mode 100644 index 000000000000..0b0aee9afa6d --- /dev/null +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.devicepolicy; + +import android.app.admin.DevicePolicyManager; +import android.os.ShellCommand; + +import java.io.PrintWriter; +import java.util.Objects; + +final class DevicePolicyManagerServiceShellCommand extends ShellCommand { + + private static final String CMD_IS_SAFE_OPERATION = "is-operation-safe"; + + private final DevicePolicyManagerService mService; + + DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service) { + mService = Objects.requireNonNull(service); + } + + @Override + public void onHelp() { + try (PrintWriter pw = getOutPrintWriter();) { + pw.printf("DevicePolicyManager Service (device_policy) commands:\n\n"); + showHelp(pw); + } + } + + @Override + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + try (PrintWriter pw = getOutPrintWriter();) { + switch (cmd) { + case CMD_IS_SAFE_OPERATION: + return runIsSafeOperation(pw); + default: + return onInvalidCommand(pw, cmd); + } + } + } + + private int onInvalidCommand(PrintWriter pw, String cmd) { + if (super.handleDefaultCommands(cmd) == 0) { + return 0; + } + + pw.println("Usage: "); + showHelp(pw); + return -1; + } + + + private void showHelp(PrintWriter pw) { + pw.printf(" help\n"); + pw.printf(" Prints this help text.\n\n"); + pw.printf(" %s <OPERATION_ID>\n", CMD_IS_SAFE_OPERATION); + pw.printf(" Checks if the give operation is safe \n\n"); + } + + private int runIsSafeOperation(PrintWriter pw) { + int operation = Integer.parseInt(getNextArgRequired()); + boolean safe = mService.canExecute(operation); + pw.printf("Operation %s is %s\n", DevicePolicyManager.operationToString(operation), + safe ? "SAFE" : "UNSAFE"); + return 0; + } +} diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java index 72d6caf1a5be..133f630b7a74 100644 --- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java +++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.metrics.LogMaker; +import android.util.IndentingPrintWriter; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -73,7 +74,7 @@ public class BatterySavingStatsTest { void assertDumpable() { final ByteArrayOutputStream out = new ByteArrayOutputStream(); - dump(new PrintWriter(out), ""); // Just make sure it won't crash. + dump(new IndentingPrintWriter(new PrintWriter(out))); // Just make sure it won't crash. } void advanceClock(int minutes) { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 3d31824e5aae..080f04efa9b4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -80,13 +80,13 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { public void testActivityFinish() { final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity(); - assertTrue("Activity must be finished", mAtm.finishActivity(activity.appToken, - 0 /* resultCode */, null /* resultData */, + assertTrue("Activity must be finished", mAtm.mActivityClientController.finishActivity( + activity.appToken, 0 /* resultCode */, null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY)); assertTrue(activity.finishing); assertTrue("Duplicate activity finish request must also return 'true'", - mAtm.finishActivity(activity.appToken, 0 /* resultCode */, + mAtm.mActivityClientController.finishActivity(activity.appToken, 0 /* resultCode */, null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY)); } @@ -225,7 +225,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { //to simulate NPE doReturn(null).when(record).getParent(); - mAtm.enterPictureInPictureMode(token, params); + mAtm.mActivityClientController.enterPictureInPictureMode(token, params); //if record's null parent is not handled gracefully, test will fail with NPE mockSession.finishMocking(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java index 8e6b6fab19eb..266ce5ba0e68 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -20,6 +20,7 @@ import static android.os.Process.INVALID_UID; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; @@ -82,7 +83,7 @@ public class DisplayAreaPolicyBuilderTest { private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy(null, null); private WindowManagerService mWms; private RootDisplayArea mRoot; - private DisplayArea<WindowContainer> mImeContainer; + private DisplayArea.Tokens mImeContainer; private DisplayContent mDisplayContent; private TaskDisplayArea mDefaultTaskDisplayArea; private List<TaskDisplayArea> mTaskDisplayAreaList; @@ -95,7 +96,7 @@ public class DisplayAreaPolicyBuilderTest { public void setup() { mWms = mSystemServices.getWindowManagerService(); mRoot = new SurfacelessDisplayAreaRoot(mWms); - mImeContainer = new DisplayArea<>(mWms, ABOVE_TASKS, "Ime"); + mImeContainer = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "ImeContainer"); mDisplayContent = mock(DisplayContent.class); mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks", FEATURE_DEFAULT_TASK_CONTAINER); @@ -148,6 +149,10 @@ public class DisplayAreaPolicyBuilderTest { // The IME is below both foo and bar. assertThat(fooDescendantMatcher.matches(mImeContainer)).isTrue(); assertThat(barDescendantMatcher.matches(mImeContainer)).isTrue(); + assertThat(policy.findAreaForToken(tokenOfType(TYPE_INPUT_METHOD))) + .isEqualTo(mImeContainer); + assertThat(policy.findAreaForToken(tokenOfType(TYPE_INPUT_METHOD_DIALOG))) + .isEqualTo(mImeContainer); List<DisplayArea<?>> actualOrder = collectLeafAreas(mRoot); Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, mImeContainer, @@ -547,7 +552,7 @@ public class DisplayAreaPolicyBuilderTest { private Map<DisplayArea<?>, Set<Integer>> calculateZSets( DisplayAreaPolicyBuilder.Result policy, - DisplayArea<WindowContainer> ime, + DisplayArea.Tokens ime, DisplayArea<Task> tasks) { Map<DisplayArea<?>, Set<Integer>> zSets = new HashMap<>(); int[] types = {TYPE_STATUS_BAR, TYPE_NAVIGATION_BAR, TYPE_PRESENTATION, diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java index 5a47493c12cd..496b2b744712 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java @@ -69,7 +69,7 @@ public class DisplayAreaPolicyTests { WindowManagerService wms = mSystemServices.getWindowManagerService(); mRoot = new SurfacelessDisplayAreaRoot(wms); spyOn(mRoot); - DisplayArea<WindowContainer> ime = new DisplayArea<>(wms, ABOVE_TASKS, "Ime"); + DisplayArea.Tokens ime = new DisplayArea.Tokens(wms, ABOVE_TASKS, "Ime"); DisplayContent displayContent = mock(DisplayContent.class); doReturn(true).when(displayContent).isTrusted(); mTaskDisplayArea1 = new TaskDisplayArea(displayContent, wms, "Tasks1", @@ -143,7 +143,7 @@ public class DisplayAreaPolicyTests { FEATURE_VENDOR_FIRST + 5); final TaskDisplayArea taskDisplayArea5 = new TaskDisplayArea(displayContent, wms, "Tasks5", FEATURE_VENDOR_FIRST + 6); - final DisplayArea<WindowContainer> ime = new DisplayArea<>(wms, ABOVE_TASKS, "Ime"); + final DisplayArea.Tokens ime = new DisplayArea.Tokens(wms, ABOVE_TASKS, "Ime"); final DisplayAreaPolicy policy = new DisplayAreaPolicyBuilder() .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(root) .setImeContainer(ime) diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java index 351426ae78b2..2d289808dd26 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java @@ -81,7 +81,7 @@ public class DisplayAreaProviderTest { @Override public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, - RootDisplayArea root, DisplayArea<? extends WindowContainer> imeContainer) { + RootDisplayArea root, DisplayArea.Tokens imeContainer) { throw new RuntimeException("test stub"); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index dba157e6ce06..f123bc16e52c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -824,7 +824,8 @@ public class WindowOrganizerTests extends WindowTestsBase { final PictureInPictureParams p = new PictureInPictureParams.Builder() .setAspectRatio(new Rational(1, 2)).build(); - assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p)); + assertTrue(mWm.mAtmService.mActivityClientController.enterPictureInPictureMode( + record.token, p)); waitUntilHandlersIdle(); assertNotNull(o.mInfo); assertNotNull(o.mInfo.pictureInPictureParams); @@ -845,14 +846,15 @@ public class WindowOrganizerTests extends WindowTestsBase { final ActivityRecord record = makePipableActivity(); final PictureInPictureParams p = new PictureInPictureParams.Builder() .setAspectRatio(new Rational(1, 2)).build(); - assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p)); + assertTrue(mWm.mAtmService.mActivityClientController.enterPictureInPictureMode( + record.token, p)); waitUntilHandlersIdle(); assertNotNull(o.mInfo); assertNotNull(o.mInfo.pictureInPictureParams); final PictureInPictureParams p2 = new PictureInPictureParams.Builder() .setAspectRatio(new Rational(3, 4)).build(); - mWm.mAtmService.setPictureInPictureParams(record.token, p2); + mWm.mAtmService.mActivityClientController.setPictureInPictureParams(record.token, p2); waitUntilHandlersIdle(); assertNotNull(o.mChangedInfo); assertNotNull(o.mChangedInfo.pictureInPictureParams); @@ -920,7 +922,7 @@ public class WindowOrganizerTests extends WindowTestsBase { assertTrue(stack2.isOrganized()); // Verify a back pressed does not call the organizer - mWm.mAtmService.onBackPressedOnTaskRoot(activity.token); + mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token); verify(organizer, never()).onBackPressedOnTaskRoot(any()); // Enable intercepting back @@ -928,7 +930,7 @@ public class WindowOrganizerTests extends WindowTestsBase { stack.mRemoteToken.toWindowContainerToken(), true); // Verify now that the back press does call the organizer - mWm.mAtmService.onBackPressedOnTaskRoot(activity.token); + mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token); verify(organizer, times(1)).onBackPressedOnTaskRoot(any()); // Disable intercepting back @@ -936,7 +938,7 @@ public class WindowOrganizerTests extends WindowTestsBase { stack.mRemoteToken.toWindowContainerToken(), false); // Verify now that the back press no longer calls the organizer - mWm.mAtmService.onBackPressedOnTaskRoot(activity.token); + mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token); verify(organizer, times(1)).onBackPressedOnTaskRoot(any()); } |