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

Commit 8ebc0db4 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12765415 from f2d99a52 to 25Q1-release

Change-Id: Iaa6e1f3d5046b22eaecabbedfa01537b9410b1eb
parents 04248d2e f2d99a52
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -34768,7 +34768,7 @@ package android.os {
    method @FlaggedApi("android.os.message_queue_testability") public boolean isBlockedOnSyncBarrier();
    method public android.os.Message next();
    method @FlaggedApi("android.os.message_queue_testability") @Nullable public Long peekWhen();
    method @FlaggedApi("android.os.message_queue_testability") @Nullable public android.os.Message pop();
    method @FlaggedApi("android.os.message_queue_testability") @Nullable public android.os.Message poll();
    method public void recycle(android.os.Message);
    method public void release();
  }
+2 −2
Original line number Diff line number Diff line
@@ -12713,14 +12713,14 @@ package android.security.authenticationpolicy {
  }
  @FlaggedApi("android.security.secure_lockdown") public final class DisableSecureLockDeviceParams implements android.os.Parcelable {
    ctor public DisableSecureLockDeviceParams(@NonNull String);
    ctor public DisableSecureLockDeviceParams(@NonNull CharSequence);
    method public int describeContents();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.security.authenticationpolicy.DisableSecureLockDeviceParams> CREATOR;
  }
  @FlaggedApi("android.security.secure_lockdown") public final class EnableSecureLockDeviceParams implements android.os.Parcelable {
    ctor public EnableSecureLockDeviceParams(@NonNull String);
    ctor public EnableSecureLockDeviceParams(@NonNull CharSequence);
    method public int describeContents();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.security.authenticationpolicy.EnableSecureLockDeviceParams> CREATOR;
+2 −1
Original line number Diff line number Diff line
@@ -214,7 +214,8 @@ public class BroadcastStickyCache {
            // We only need 1 entry per cache but just to be on the safer side we are choosing 32
            // although we don't expect more than 1.
            sActionConfigMap.put(action,
                    new Config(32, IpcDataCache.MODULE_SYSTEM, sActionApiNameMap.get(action)));
                    new Config(32, IpcDataCache.MODULE_SYSTEM,
                            sActionApiNameMap.get(action)).cacheNulls(true));
        }

        return sActionConfigMap.get(action);
+15 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.view.ViewTreeObserver;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * This class is responsible for registering callbacks that will receive JankData batches.
@@ -173,6 +174,15 @@ public class JankTracker {
        mStateTracker.retrieveAllStates(stateDataList);
    }

    /**
     * Retrieve all pending jank stats before they are logged, this is intended for testing
     * purposes only.
     */
    @VisibleForTesting
    public HashMap<String, JankDataProcessor.PendingJankStat> getPendingJankStats() {
        return mJankDataProcessor.getPendingJankStats();
    }

    /**
     * Only intended to be used by tests, the runnable that registers the listeners may not run
     * in time for tests to pass. This forces them to run immediately.
@@ -192,7 +202,11 @@ public class JankTracker {
         */
    }

    private boolean shouldTrack() {
    /**
     * Returns whether jank tracking is enabled or not.
     */
    @VisibleForTesting
    public boolean shouldTrack() {
        return mTrackingEnabled && mListenersRegistered;
    }

+114 −1
Original line number Diff line number Diff line
@@ -37,36 +37,44 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.Intent.FilterComparison;
import android.content.IntentSender;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
import android.widget.RemoteViews;

import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FunctionalUtils;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * Updates AppWidget state; gets information about installed AppWidget providers and other
@@ -592,6 +600,8 @@ public class AppWidgetManager {

    private boolean mHasPostedLegacyLists = false;

    private @NonNull ServiceCollectionCache mServiceCollectionCache;

    /**
     * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
     * Context} object.
@@ -612,6 +622,7 @@ public class AppWidgetManager {
        mPackageName = context.getOpPackageName();
        mService = service;
        mDisplayMetrics = context.getResources().getDisplayMetrics();
        mServiceCollectionCache = new ServiceCollectionCache(context, /* timeout= */ 5000L);
        if (mService == null) {
            return;
        }
@@ -649,7 +660,7 @@ public class AppWidgetManager {
            final RemoteViews viewsCopy = new RemoteViews(original);
            Runnable updateWidgetWithTask = () -> {
                try {
                    viewsCopy.collectAllIntents(mMaxBitmapMemory).get();
                    viewsCopy.collectAllIntents(mMaxBitmapMemory, mServiceCollectionCache).get();
                    action.acceptOrThrow(viewsCopy);
                } catch (Exception e) {
                    Log.e(TAG, failureMsg, e);
@@ -1629,4 +1640,106 @@ public class AppWidgetManager {
        thread.start();
        return thread.getThreadHandler();
    }

    /**
     * @hide
     */
    public static class ServiceCollectionCache {

        private final Context mContext;
        private final Handler mHandler;
        private final long mTimeOut;

        private final Map<FilterComparison, ConnectionTask> mActiveConnections =
                new ArrayMap<>();

        public ServiceCollectionCache(Context context, long timeOut) {
            mContext = context;
            mHandler = new Handler(BackgroundThread.getHandler().getLooper());
            mTimeOut = timeOut;
        }

        /**
         * Connect to the service indicated by the {@code Intent}, and consume the binder on the
         * specified executor
         */
        public void connectAndConsume(Intent intent, Consumer<IBinder> task, Executor executor) {
            mHandler.post(() -> connectAndConsumeInner(intent, task, executor));
        }

        private void connectAndConsumeInner(Intent intent, Consumer<IBinder> task,
                Executor executor) {
            ConnectionTask activeConnection = mActiveConnections.computeIfAbsent(
                    new FilterComparison(intent), ConnectionTask::new);
            activeConnection.add(task, executor);
        }

        private class ConnectionTask implements ServiceConnection {

            private final Runnable mDestroyAfterTimeout = this::onDestroyTimeout;
            private final ArrayDeque<Pair<Consumer<IBinder>, Executor>> mTaskQueue =
                    new ArrayDeque<>();

            private boolean mOnDestroyTimeout = false;
            private IBinder mIBinder;

            ConnectionTask(@NonNull FilterComparison filter) {
                mContext.bindService(filter.getIntent(),
                        Context.BindServiceFlags.of(Context.BIND_AUTO_CREATE),
                        mHandler::post,
                        this);
            }

            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                mIBinder = iBinder;
                mHandler.post(this::handleNext);
            }

            @Override
            public void onNullBinding(ComponentName name) {
                // Use an empty binder, follow up tasks will handle the failure
                onServiceConnected(name, new Binder());
            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) { }

            void add(Consumer<IBinder> task, Executor executor) {
                mTaskQueue.add(Pair.create(task, executor));
                if (mOnDestroyTimeout) {
                    // If we are waiting for timeout, cancel it and execute the next task
                    handleNext();
                }
            }

            private void handleNext() {
                mHandler.removeCallbacks(mDestroyAfterTimeout);
                Pair<Consumer<IBinder>, Executor> next = mTaskQueue.pollFirst();
                if (next != null) {
                    mOnDestroyTimeout = false;
                    next.second.execute(() -> {
                        next.first.accept(mIBinder);
                        mHandler.post(this::handleNext);
                    });
                } else {
                    // Finished all tasks, start a timeout to unbind this service
                    mOnDestroyTimeout = true;
                    mHandler.postDelayed(mDestroyAfterTimeout, mTimeOut);
                }
            }

            /**
             * Called after we have waited for {@link #mTimeOut} after the last task is finished
             */
            private void onDestroyTimeout() {
                if (!mTaskQueue.isEmpty()) {
                    handleNext();
                    return;
                }
                mContext.unbindService(this);
                mActiveConnections.values().remove(this);
            }
        }
    }
}
Loading