Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af6aec86 authored by Joanne Chung's avatar Joanne Chung Committed by Android (Google) Code Review
Browse files

Merge "Optimization: find views in single traversal." into sc-dev

parents 6a26f105 401900c9
Loading
Loading
Loading
Loading
+45 −11
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
import android.view.autofill.AutofillId;
import android.view.translation.UiTranslationManager.UiTranslationState;

@@ -194,24 +197,19 @@ public class UiTranslationController {
    private void onUiTranslationStarted(Translator translator, List<AutofillId> views) {
        synchronized (mLock) {
            // Find Views collect the translation data
            // TODO(b/178084101): try to optimize, e.g. to this in a single traversal
            final int viewCounts = views.size();
            final ArrayList<TranslationRequest> requests = new ArrayList<>();
            for (int i = 0; i < viewCounts; i++) {
                final AutofillId viewAutofillId = views.get(i);
                final View view = mActivity.findViewByAutofillIdTraversal(viewAutofillId);
                if (view == null) {
                    Log.w(TAG, "Can not find the View for autofill id= " + viewAutofillId);
                    continue;
                }
                mViews.put(viewAutofillId, new WeakReference<>(view));
            final ArrayList<View> foundViews = new ArrayList<>();
            findViewsTraversalByAutofillIds(views, foundViews);
            for (int i = 0; i < foundViews.size(); i++) {
                final View view = foundViews.get(i);
                final int currentCount = i;
                mActivity.runOnUiThread(() -> {
                    final TranslationRequest translationRequest = view.onCreateTranslationRequest();
                    if (translationRequest != null
                            && translationRequest.getTranslationText().length() > 0) {
                        requests.add(translationRequest);
                    }
                    if (requests.size() == viewCounts) {
                    if (currentCount == (foundViews.size() - 1)) {
                        Log.v(TAG, "onUiTranslationStarted: send " + requests.size() + " request.");
                        mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
                                UiTranslationController::sendTranslationRequest,
@@ -222,6 +220,42 @@ public class UiTranslationController {
        }
    }

    private void findViewsTraversalByAutofillIds(List<AutofillId> sourceViewIds,
            ArrayList<View> foundViews) {
        final ArrayList<ViewRootImpl> roots =
                WindowManagerGlobal.getInstance().getRootViews(mActivity.getActivityToken());
        for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
            final View rootView = roots.get(rootNum).getView();
            if (rootView instanceof ViewGroup) {
                findViewsTraversalByAutofillIds((ViewGroup) rootView, sourceViewIds, foundViews);
            } else {
                addViewIfNeeded(sourceViewIds, rootView, foundViews);
            }
        }
    }

    private void findViewsTraversalByAutofillIds(ViewGroup viewGroup,
            List<AutofillId> sourceViewIds, ArrayList<View> foundViews) {
        final int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; ++i) {
            final View child = viewGroup.getChildAt(i);
            if (child instanceof ViewGroup) {
                findViewsTraversalByAutofillIds((ViewGroup) child, sourceViewIds, foundViews);
            } else {
                addViewIfNeeded(sourceViewIds, child, foundViews);
            }
        }
    }

    private void addViewIfNeeded(List<AutofillId> sourceViewIds, View view,
            ArrayList<View> foundViews) {
        final AutofillId autofillId = view.getAutofillId();
        if (sourceViewIds.contains(autofillId)) {
            mViews.put(autofillId, new WeakReference<>(view));
            foundViews.add(view);
        }
    }

    private void runForEachView(Consumer<View> action) {
        synchronized (mLock) {
            final ArrayMap<AutofillId, WeakReference<View>> views = new ArrayMap<>(mViews);