diff options
6 files changed, 132 insertions, 64 deletions
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING index 8ad33dbf9f4a..b65ae7a0a7b9 100644 --- a/core/java/android/app/TEST_MAPPING +++ b/core/java/android/app/TEST_MAPPING @@ -29,6 +29,15 @@ }, { "file_patterns": ["(/|^)AppOpsManager.java"], + "name": "CtsStatsdHostTestCases", + "options": [ + { + "include-filter": "android.cts.statsd.atom.UidAtomTests#testAppOps" + } + ] + }, + { + "file_patterns": ["(/|^)AppOpsManager.java"], "name": "CtsPermission2TestCases", "options": [ { diff --git a/core/java/android/inputmethodservice/InlineSuggestionSessionController.java b/core/java/android/inputmethodservice/InlineSuggestionSessionController.java index 8c0dd2a9bf59..071c096ee2f0 100644 --- a/core/java/android/inputmethodservice/InlineSuggestionSessionController.java +++ b/core/java/android/inputmethodservice/InlineSuggestionSessionController.java @@ -134,6 +134,7 @@ class InlineSuggestionSessionController { mImeClientFieldId = imeFieldId; if (mSession != null) { + mSession.consumeInlineSuggestionsResponse(InlineSuggestionSession.EMPTY_RESPONSE); // Initiates the callback to Autofill if there is a pending matching session. // Otherwise updates the session with the Ime status. if (!mSession.isCallbackInvoked() && match(mSession.getRequestInfo())) { @@ -213,7 +214,6 @@ class InlineSuggestionSessionController { mImeInputViewStarted = false; mImeInputStarted = false; if (mSession != null && mSession.shouldSendImeStatus()) { - mSession.consumeInlineSuggestionsResponse(InlineSuggestionSession.EMPTY_RESPONSE); try { mSession.getRequestCallback().onInputMethodFinishInput(); } catch (RemoteException e) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b860bac0d001..896a2de8b135 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1726,8 +1726,10 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); } } + scheduleConsumeBatchedInputImmediately(); } + /** Register callbacks to be notified when the ViewRootImpl surface changes. */ interface SurfaceChangedCallback { void surfaceCreated(Transaction t); @@ -8107,7 +8109,9 @@ public final class ViewRootImpl implements ViewParent, } void scheduleConsumeBatchedInput() { - if (!mConsumeBatchedInputScheduled) { + // If anything is currently scheduled to consume batched input then there's no point in + // scheduling it again. + if (!mConsumeBatchedInputScheduled && !mConsumeBatchedInputImmediatelyScheduled) { mConsumeBatchedInputScheduled = true; mChoreographer.postCallback(Choreographer.CALLBACK_INPUT, mConsumedBatchedInputRunnable, null); @@ -8130,22 +8134,15 @@ public final class ViewRootImpl implements ViewParent, } } - void doConsumeBatchedInput(long frameTimeNanos) { - if (mConsumeBatchedInputScheduled) { - mConsumeBatchedInputScheduled = false; - if (mInputEventReceiver != null) { - if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos) - && frameTimeNanos != -1) { - // If we consumed a batch here, we want to go ahead and schedule the - // consumption of batched input events on the next frame. Otherwise, we would - // wait until we have more input events pending and might get starved by other - // things occurring in the process. If the frame time is -1, however, then - // we're in a non-batching mode, so there's no need to schedule this. - scheduleConsumeBatchedInput(); - } - } - doProcessInputEvents(); + boolean doConsumeBatchedInput(long frameTimeNanos) { + final boolean consumedBatches; + if (mInputEventReceiver != null) { + consumedBatches = mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos); + } else { + consumedBatches = false; } + doProcessInputEvents(); + return consumedBatches; } final class TraversalRunnable implements Runnable { @@ -8189,8 +8186,11 @@ public final class ViewRootImpl implements ViewParent, @Override public void onBatchedInputEventPending(int source) { + // mStopped: There will be no more choreographer callbacks if we are stopped, + // so we must consume all input immediately to prevent ANR final boolean unbuffered = mUnbufferedInputDispatch - || (source & mUnbufferedInputSource) != SOURCE_CLASS_NONE; + || (source & mUnbufferedInputSource) != SOURCE_CLASS_NONE + || mStopped; if (unbuffered) { if (mConsumeBatchedInputScheduled) { unscheduleConsumeBatchedInput(); @@ -8218,7 +8218,14 @@ public final class ViewRootImpl implements ViewParent, final class ConsumeBatchedInputRunnable implements Runnable { @Override public void run() { - doConsumeBatchedInput(mChoreographer.getFrameTimeNanos()); + mConsumeBatchedInputScheduled = false; + if (doConsumeBatchedInput(mChoreographer.getFrameTimeNanos())) { + // If we consumed a batch here, we want to go ahead and schedule the + // consumption of batched input events on the next frame. Otherwise, we would + // wait until we have more input events pending and might get starved by other + // things occurring in the process. + scheduleConsumeBatchedInput(); + } } } final ConsumeBatchedInputRunnable mConsumedBatchedInputRunnable = @@ -8228,6 +8235,7 @@ public final class ViewRootImpl implements ViewParent, final class ConsumeBatchedInputImmediatelyRunnable implements Runnable { @Override public void run() { + mConsumeBatchedInputImmediatelyScheduled = false; doConsumeBatchedInput(-1); } } diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index de5ab6f1c90d..31e6cb9b5591 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -95,6 +95,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mSelectableTargetInfoCommunicator; private int mNumShortcutResults = 0; + private Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>(); // Reserve spots for incoming direct share targets by adding placeholders private ChooserTargetInfo @@ -239,11 +240,42 @@ public class ChooserListAdapter extends ResolverListAdapter { @Override protected void onBindView(View view, TargetInfo info, int position) { - super.onBindView(view, info, position); - if (info == null) return; + final ViewHolder holder = (ViewHolder) view.getTag(); + if (info == null) { + holder.icon.setImageDrawable( + mContext.getDrawable(R.drawable.resolver_icon_placeholder)); + return; + } + + if (!(info instanceof DisplayResolveInfo)) { + holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel()); + holder.bindIcon(info); + + if (info instanceof SelectableTargetInfo) { + // direct share targets should append the application name for a better readout + DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo(); + CharSequence appName = rInfo != null ? rInfo.getDisplayLabel() : ""; + CharSequence extendedInfo = info.getExtendedInfo(); + String contentDescription = String.join(" ", info.getDisplayLabel(), + extendedInfo != null ? extendedInfo : "", appName); + holder.updateContentDescription(contentDescription); + } + } else { + DisplayResolveInfo dri = (DisplayResolveInfo) info; + holder.bindLabel(dri.getDisplayLabel(), dri.getExtendedInfo(), alwaysShowSubLabel()); + LoadIconTask task = mIconLoaders.get(dri); + if (task == null) { + task = new LoadIconTask(dri, holder); + mIconLoaders.put(dri, task); + task.execute(); + } else { + // The holder was potentially changed as the underlying items were + // reshuffled, so reset the target holder + task.setViewHolder(holder); + } + } // If target is loading, show a special placeholder shape in the label, make unclickable - final ViewHolder holder = (ViewHolder) view.getTag(); if (info instanceof ChooserActivity.PlaceHolderTargetInfo) { final int maxWidth = mContext.getResources().getDimensionPixelSize( R.dimen.chooser_direct_share_label_placeholder_max_width); diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 094fb1e2f23c..eef722e32bdc 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -54,7 +54,6 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.DisplayResolveInfo; -import com.android.internal.app.chooser.SelectableTargetInfo; import com.android.internal.app.chooser.TargetInfo; import java.util.ArrayList; @@ -68,7 +67,7 @@ public class ResolverListAdapter extends BaseAdapter { private final List<ResolveInfo> mBaseResolveList; private final PackageManager mPm; protected final Context mContext; - private final ColorMatrixColorFilter mSuspendedMatrixColorFilter; + private static ColorMatrixColorFilter sSuspendedMatrixColorFilter; private final int mIconDpi; protected ResolveInfo mLastChosen; private DisplayResolveInfo mOtherProfile; @@ -103,7 +102,6 @@ public class ResolverListAdapter extends BaseAdapter { mDisplayList = new ArrayList<>(); mFilterLastUsed = filterLastUsed; mResolverListController = resolverListController; - mSuspendedMatrixColorFilter = createSuspendedColorMatrix(); mResolverListCommunicator = resolverListCommunicator; mIsAudioCaptureDevice = isAudioCaptureDevice; final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE); @@ -541,28 +539,13 @@ public class ResolverListAdapter extends BaseAdapter { getLoadLabelTask((DisplayResolveInfo) info, holder).execute(); } else { holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel()); - if (info instanceof SelectableTargetInfo) { - // direct share targets should append the application name for a better readout - DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo(); - CharSequence appName = rInfo != null ? rInfo.getDisplayLabel() : ""; - CharSequence extendedInfo = info.getExtendedInfo(); - String contentDescription = String.join(" ", info.getDisplayLabel(), - extendedInfo != null ? extendedInfo : "", appName); - holder.updateContentDescription(contentDescription); - } - } - - if (info.isSuspended()) { - holder.icon.setColorFilter(mSuspendedMatrixColorFilter); - } else { - holder.icon.setColorFilter(null); } if (info instanceof DisplayResolveInfo && !((DisplayResolveInfo) info).hasDisplayIcon()) { - new ResolverListAdapter.LoadIconTask((DisplayResolveInfo) info, holder.icon).execute(); + new LoadIconTask((DisplayResolveInfo) info, holder).execute(); } else { - holder.icon.setImageDrawable(info.getDisplayIcon(mContext)); + holder.bindIcon(info); } } @@ -580,23 +563,27 @@ public class ResolverListAdapter extends BaseAdapter { } } - private ColorMatrixColorFilter createSuspendedColorMatrix() { - int grayValue = 127; - float scale = 0.5f; // half bright + private static ColorMatrixColorFilter getSuspendedColorMatrix() { + if (sSuspendedMatrixColorFilter == null) { + + int grayValue = 127; + float scale = 0.5f; // half bright - ColorMatrix tempBrightnessMatrix = new ColorMatrix(); - float[] mat = tempBrightnessMatrix.getArray(); - mat[0] = scale; - mat[6] = scale; - mat[12] = scale; - mat[4] = grayValue; - mat[9] = grayValue; - mat[14] = grayValue; + ColorMatrix tempBrightnessMatrix = new ColorMatrix(); + float[] mat = tempBrightnessMatrix.getArray(); + mat[0] = scale; + mat[6] = scale; + mat[12] = scale; + mat[4] = grayValue; + mat[9] = grayValue; + mat[14] = grayValue; - ColorMatrix matrix = new ColorMatrix(); - matrix.setSaturation(0.0f); - matrix.preConcat(tempBrightnessMatrix); - return new ColorMatrixColorFilter(matrix); + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0.0f); + matrix.preConcat(tempBrightnessMatrix); + sSuspendedMatrixColorFilter = new ColorMatrixColorFilter(matrix); + } + return sSuspendedMatrixColorFilter; } ActivityInfoPresentationGetter makePresentationGetter(ActivityInfo ai) { @@ -615,7 +602,17 @@ public class ResolverListAdapter extends BaseAdapter { void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) { final DisplayResolveInfo iconInfo = getFilteredItem(); if (iconView != null && iconInfo != null) { - new LoadIconTask(iconInfo, iconView).execute(); + new AsyncTask<Void, Void, Drawable>() { + @Override + protected Drawable doInBackground(Void... params) { + return loadIconForResolveInfo(iconInfo.getResolveInfo()); + } + + @Override + protected void onPostExecute(Drawable d) { + iconView.setImageDrawable(d); + } + }.execute(); } } @@ -708,6 +705,15 @@ public class ResolverListAdapter extends BaseAdapter { public void updateContentDescription(String description) { itemView.setContentDescription(description); } + + public void bindIcon(TargetInfo info) { + icon.setImageDrawable(info.getDisplayIcon(itemView.getContext())); + if (info.isSuspended()) { + icon.setColorFilter(getSuspendedColorMatrix()); + } else { + icon.setColorFilter(null); + } + } } protected class LoadLabelTask extends AsyncTask<Void, Void, CharSequence[]> { @@ -761,14 +767,14 @@ public class ResolverListAdapter extends BaseAdapter { } class LoadIconTask extends AsyncTask<Void, Void, Drawable> { - protected final com.android.internal.app.chooser.DisplayResolveInfo mDisplayResolveInfo; + protected final DisplayResolveInfo mDisplayResolveInfo; private final ResolveInfo mResolveInfo; - private final ImageView mTargetView; + private ViewHolder mHolder; - LoadIconTask(DisplayResolveInfo dri, ImageView target) { + LoadIconTask(DisplayResolveInfo dri, ViewHolder holder) { mDisplayResolveInfo = dri; mResolveInfo = dri.getResolveInfo(); - mTargetView = target; + mHolder = holder; } @Override @@ -782,9 +788,14 @@ public class ResolverListAdapter extends BaseAdapter { mResolverListCommunicator.updateProfileViewButton(); } else { mDisplayResolveInfo.setDisplayIcon(d); - mTargetView.setImageDrawable(d); + mHolder.bindIcon(mDisplayResolveInfo); } } + + public void setViewHolder(ViewHolder holder) { + mHolder = holder; + mHolder.bindIcon(mDisplayResolveInfo); + } } /** diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING index a3baa7e8bdea..00bbacc089a2 100644 --- a/services/core/java/com/android/server/appop/TEST_MAPPING +++ b/services/core/java/com/android/server/appop/TEST_MAPPING @@ -43,6 +43,14 @@ "include-filter": "android.app.cts.ActivityManagerApi29Test" } ] - } + }, + { + "name": "CtsStatsdHostTestCases", + "options": [ + { + "include-filter": "android.cts.statsd.atom.UidAtomTests#testAppOps" + } + ] + } ] } |