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

Commit 789de351 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8671920 from c25b379f to tm-qpr1-release

Change-Id: Icbeb98dcd5fe8c3cc8ec127540111c8005240c25
parents 22451c5e c25b379f
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -280,6 +280,20 @@ public interface AppStandbyInternal {
     */
    boolean shouldNoteResponseEventForAllBroadcastSessions();

    /**
     * Returns the list of roles whose holders are exempted from the requirement of starting
     * a response event after receiving a broadcast.
     */
    @NonNull
    List<String> getBroadcastResponseExemptedRoles();

    /**
     * Returns the list of permissions whose holders are exempted from the requirement of starting
     * a response event after receiving a broadcast.
     */
    @NonNull
    List<String> getBroadcastResponseExemptedPermissions();

    /**
     * Return the last known value corresponding to the {@code key} from
     * {@link android.provider.DeviceConfig#NAMESPACE_APP_STANDBY} in AppStandbyController.
+73 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings.Global;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
@@ -420,6 +421,26 @@ public class AppStandbyController
    volatile boolean mNoteResponseEventForAllBroadcastSessions =
            ConstantsObserver.DEFAULT_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS;

    /**
     * List of roles whose holders are exempted from the requirement of starting
     * a response event after receiving a broadcast.
     *
     * The list of roles will be separated by '|' in the string.
     */
    volatile String mBroadcastResponseExemptedRoles =
            ConstantsObserver.DEFAULT_BROADCAST_RESPONSE_EXEMPTED_ROLES;
    volatile List<String> mBroadcastResponseExemptedRolesList = Collections.EMPTY_LIST;

    /**
     * List of permissions whose holders are exempted from the requirement of starting
     * a response event after receiving a broadcast.
     *
     * The list of permissions will be separated by '|' in the string.
     */
    volatile String mBroadcastResponseExemptedPermissions =
            ConstantsObserver.DEFAULT_BROADCAST_RESPONSE_EXEMPTED_PERMISSIONS;
    volatile List<String> mBroadcastResponseExemptedPermissionsList = Collections.EMPTY_LIST;

    /**
     * Map of last known values of keys in {@link DeviceConfig#NAMESPACE_APP_STANDBY}.
     *
@@ -1959,6 +1980,18 @@ public class AppStandbyController
        return mNoteResponseEventForAllBroadcastSessions;
    }

    @Override
    @NonNull
    public List<String> getBroadcastResponseExemptedRoles() {
        return mBroadcastResponseExemptedRolesList;
    }

    @Override
    @NonNull
    public List<String> getBroadcastResponseExemptedPermissions() {
        return mBroadcastResponseExemptedPermissionsList;
    }

    @Override
    @Nullable
    public String getAppStandbyConstant(@NonNull String key) {
@@ -2311,6 +2344,14 @@ public class AppStandbyController
        pw.print(mNoteResponseEventForAllBroadcastSessions);
        pw.println();

        pw.print("  mBroadcastResponseExemptedRoles");
        pw.print(mBroadcastResponseExemptedRoles);
        pw.println();

        pw.print("  mBroadcastResponseExemptedPermissions");
        pw.print(mBroadcastResponseExemptedPermissions);
        pw.println();

        pw.println();
        pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
        pw.print(" mAllowRestrictedBucket=");
@@ -2795,6 +2836,10 @@ public class AppStandbyController
                "broadcast_sessions_with_response_duration_ms";
        private static final String KEY_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS =
                "note_response_event_for_all_broadcast_sessions";
        private static final String KEY_BROADCAST_RESPONSE_EXEMPTED_ROLES =
                "brodacast_response_exempted_roles";
        private static final String KEY_BROADCAST_RESPONSE_EXEMPTED_PERMISSIONS =
                "brodacast_response_exempted_permissions";

        public static final long DEFAULT_CHECK_IDLE_INTERVAL_MS =
                COMPRESS_TIME ? ONE_MINUTE : 4 * ONE_HOUR;
@@ -2837,6 +2882,11 @@ public class AppStandbyController
                2 * ONE_MINUTE;
        public static final boolean DEFAULT_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS =
                true;
        private static final String DEFAULT_BROADCAST_RESPONSE_EXEMPTED_ROLES = "";
        private static final String DEFAULT_BROADCAST_RESPONSE_EXEMPTED_PERMISSIONS = "";

        private final TextUtils.SimpleStringSplitter mStringPipeSplitter =
                new TextUtils.SimpleStringSplitter('|');

        ConstantsObserver(Handler handler) {
            super(handler);
@@ -2989,6 +3039,20 @@ public class AppStandbyController
                                    KEY_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS,
                                    DEFAULT_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS);
                            break;
                        case KEY_BROADCAST_RESPONSE_EXEMPTED_ROLES:
                            mBroadcastResponseExemptedRoles = properties.getString(
                                    KEY_BROADCAST_RESPONSE_EXEMPTED_ROLES,
                                    DEFAULT_BROADCAST_RESPONSE_EXEMPTED_ROLES);
                            mBroadcastResponseExemptedRolesList = splitPipeSeparatedString(
                                    mBroadcastResponseExemptedRoles);
                            break;
                        case KEY_BROADCAST_RESPONSE_EXEMPTED_PERMISSIONS:
                            mBroadcastResponseExemptedPermissions = properties.getString(
                                    KEY_BROADCAST_RESPONSE_EXEMPTED_PERMISSIONS,
                                    DEFAULT_BROADCAST_RESPONSE_EXEMPTED_PERMISSIONS);
                            mBroadcastResponseExemptedPermissionsList = splitPipeSeparatedString(
                                    mBroadcastResponseExemptedPermissions);
                            break;
                        default:
                            if (!timeThresholdsUpdated
                                    && (name.startsWith(KEY_PREFIX_SCREEN_TIME_THRESHOLD)
@@ -3003,6 +3067,15 @@ public class AppStandbyController
            }
        }

        private List<String> splitPipeSeparatedString(String string) {
            final List<String> values = new ArrayList<>();
            mStringPipeSplitter.setString(string);
            while (mStringPipeSplitter.hasNext()) {
                values.add(mStringPipeSplitter.next());
            }
            return values;
        }

        private void updateTimeThresholds() {
            // Query the values as an atomic set.
            final DeviceConfig.Properties screenThresholdProperties =
+5 −0
Original line number Diff line number Diff line
@@ -8260,6 +8260,11 @@ public class Activity extends ContextThemeWrapper
        return mMainThread;
    }

    /** @hide */
    public final ActivityInfo getActivityInfo() {
        return mActivityInfo;
    }

    final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }
+22 −3
Original line number Diff line number Diff line
@@ -298,6 +298,11 @@ public final class ActivityThread extends ClientTransactionHandler
    /** Use background GC policy and default JIT threshold. */
    private static final int VM_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;

    /** The delay time for retrying to request DirectActions. */
    private static final long REQUEST_DIRECT_ACTIONS_RETRY_TIME_MS = 200;
    /** The max count for retrying to request DirectActions. */
    private static final int REQUEST_DIRECT_ACTIONS_RETRY_MAX_COUNT = 7;

    /**
     * Denotes an invalid sequence number corresponding to a process state change.
     */
@@ -1864,7 +1869,8 @@ public final class ActivityThread extends ClientTransactionHandler
                cancellationCallback.sendResult(cancellationResult);
            }
            mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handleRequestDirectActions,
                    ActivityThread.this, activityToken, interactor, cancellationSignal, callback));
                    ActivityThread.this, activityToken, interactor, cancellationSignal, callback,
                    REQUEST_DIRECT_ACTIONS_RETRY_MAX_COUNT));
        }

        @Override
@@ -3940,7 +3946,7 @@ public final class ActivityThread extends ClientTransactionHandler
    /** Fetches the user actions for the corresponding activity */
    private void handleRequestDirectActions(@NonNull IBinder activityToken,
            @NonNull IVoiceInteractor interactor, @NonNull CancellationSignal cancellationSignal,
            @NonNull RemoteCallback callback) {
            @NonNull RemoteCallback callback, int retryCount) {
        final ActivityClientRecord r = mActivities.get(activityToken);
        if (r == null) {
            Log.w(TAG, "requestDirectActions(): no activity for " + activityToken);
@@ -3948,7 +3954,20 @@ public final class ActivityThread extends ClientTransactionHandler
            return;
        }
        final int lifecycleState = r.getLifecycleState();
        if (lifecycleState < ON_START || lifecycleState >= ON_STOP) {
        if (lifecycleState < ON_START) {
            // TODO(b/234173463): requestDirectActions callback should indicate errors
            if (retryCount > 0) {
                mH.sendMessageDelayed(
                        PooledLambda.obtainMessage(ActivityThread::handleRequestDirectActions,
                                ActivityThread.this, activityToken, interactor, cancellationSignal,
                                callback, retryCount - 1), REQUEST_DIRECT_ACTIONS_RETRY_TIME_MS);
                return;
            }
            Log.w(TAG, "requestDirectActions(" + r + "): wrong lifecycle: " + lifecycleState);
            callback.sendResult(null);
            return;
        }
        if (lifecycleState >= ON_STOP) {
            Log.w(TAG, "requestDirectActions(" + r + "): wrong lifecycle: " + lifecycleState);
            callback.sendResult(null);
            return;
+52 −65
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.internal.graphics.cam.Cam;
import com.android.internal.graphics.palette.CelebiQuantizer;
import com.android.internal.graphics.palette.Palette;
import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
import com.android.internal.util.ContrastColorUtil;

import java.io.FileOutputStream;
import java.lang.annotation.Retention;
@@ -93,10 +94,18 @@ public final class WallpaperColors implements Parcelable {
    // using the area instead. This way our comparisons are aspect ratio independent.
    private static final int MAX_WALLPAPER_EXTRACTION_AREA = MAX_BITMAP_SIZE * MAX_BITMAP_SIZE;

    // Decides when dark theme is optimal for this wallpaper.
    // The midpoint of perceptual luminance, 50, is 18.42 in relative luminance.
    // ColorUtils.calculateLuminance returns relative luminance on a scale from 0 to 1.
    private static final float DARK_THEME_MEAN_LUMINANCE = 0.1842f;
    // When extracting the main colors, only consider colors
    // present in at least MIN_COLOR_OCCURRENCE of the image
    private static final float MIN_COLOR_OCCURRENCE = 0.05f;

    // Decides when dark theme is optimal for this wallpaper
    private static final float DARK_THEME_MEAN_LUMINANCE = 0.3f;
    // Minimum mean luminosity that an image needs to have to support dark text
    private static final float BRIGHT_IMAGE_MEAN_LUMINANCE = 0.7f;
    // We also check if the image has dark pixels in it,
    // to avoid bright images with some dark spots.
    private static final float DARK_PIXEL_CONTRAST = 5.5f;
    private static final float MAX_DARK_AREA = 0.05f;

    private final List<Color> mMainColors;
    private final Map<Integer, Integer> mAllColors;
@@ -244,9 +253,12 @@ public final class WallpaperColors implements Parcelable {
        this(primaryColor, secondaryColor, tertiaryColor, 0);

        // Calculate dark theme support based on primary color.
        final double relativeLuminance = ColorUtils.calculateLuminance(primaryColor.toArgb());
        final boolean wallpaperIsDark = relativeLuminance < DARK_THEME_MEAN_LUMINANCE;
        mColorHints |= wallpaperIsDark ? HINT_SUPPORTS_DARK_THEME : HINT_SUPPORTS_DARK_TEXT;
        final float[] tmpHsl = new float[3];
        ColorUtils.colorToHSL(primaryColor.toArgb(), tmpHsl);
        final float luminance = tmpHsl[2];
        if (luminance < DARK_THEME_MEAN_LUMINANCE) {
            mColorHints |= HINT_SUPPORTS_DARK_THEME;
        }
    }

    /**
@@ -524,6 +536,9 @@ public final class WallpaperColors implements Parcelable {

        dimAmount = MathUtils.saturate(dimAmount);
        int[] pixels = new int[source.getWidth() * source.getHeight()];
        double totalLuminance = 0;
        final int maxDarkPixels = (int) (pixels.length * MAX_DARK_AREA);
        int darkPixels = 0;
        source.getPixels(pixels, 0 /* offset */, source.getWidth(), 0 /* x */, 0 /* y */,
                source.getWidth(), source.getHeight());

@@ -532,70 +547,42 @@ public final class WallpaperColors implements Parcelable {
        int dimmingLayerAlpha = (int) (255 * dimAmount);
        int blackTransparent = ColorUtils.setAlphaComponent(Color.BLACK, dimmingLayerAlpha);

        // The median luminance in the wallpaper will be used to decide if it is light or dark.
        //
        // Calculating the luminances, adding them to a data structure, then selecting
        // the middle element would be expensive, the sort would be O(n), where n is the number
        // of pixels.
        //
        // Instead, we create an integer array with 101 elements initialized to zero.
        // Why 101? 0 through 100, inclusive, matching the range of luminance.
        // Then, for each pixel, the luminance is calculated, and the integer at the array index
        // equal to the rounded luminance is incremented.
        //
        // After processing the pixels, the median luminance is determined by iterating over the
        // array containing the count for each luminance. Starting from 0, we adding the count at
        // each index until pixels.length/2 is exceeded. When that occurs, it means the current
        // array index contains the pixel of median luminance, thus the current array index is the
        // median luminance.
        int[] luminanceCounts = new int[101];
        // This bitmap was already resized to fit the maximum allowed area.
        // Let's just loop through the pixels, no sweat!
        float[] tmpHsl = new float[3];
        for (int i = 0; i < pixels.length; i++) {
            int pixelColor = pixels[i];
            ColorUtils.colorToHSL(pixelColor, tmpHsl);
            final int alpha = Color.alpha(pixelColor);
            if (alpha == 0) {
                continue;
            }

            // If the wallpaper is dimmed, apply dimming before calculating luminance.
            int compositeColor = dimAmount <= 0 ? pixelColor :
                    ColorUtils.compositeColors(blackTransparent, pixelColor);

            // calculateLuminance will return relative luminance on a scale from 0 to 1. Intent
            // is normalize to 0 to 100, and that is done by defensively normalizing to
            // luminanceCounts.length, then flooring the result to defensively avoid any imprecision
            // in the result of calculateLuminance that could cause it to exceed 1 and thus the
            // array bounds.
            float relativeLuminance = (float) ColorUtils.calculateLuminance(compositeColor)
                    * luminanceCounts.length - 1;
            int intRelativeLuminance = (int) Math.floor(relativeLuminance);
            int clampedRelativeLuminance = (intRelativeLuminance < 0) ? 0 :
                    (intRelativeLuminance > luminanceCounts.length - 1) ? luminanceCounts.length - 1
                            : intRelativeLuminance;
            luminanceCounts[clampedRelativeLuminance] += 1;
        }

        int criticalRelativeLuminance = 0;
        int luminancesProcessed = 0;
        int criticalLuminanceIndex = (int) Math.floor(pixels.length * 0.5);
        for (int i = 0; i < 100; i++) {
            luminancesProcessed += luminanceCounts[i];
            if (luminancesProcessed > criticalLuminanceIndex) {
                criticalRelativeLuminance = i;
                break;
            }
        }

        // Wallpaper is dark if the median pixel is less than mid-gray.
        //
        // Relative luminance places mid-gray at 18.42, 19 is used since luminances were rounded to
        // ints to be stored in the array.
        //
        // Why not use perceptual luminance? It would require one more conversion step at each
        // pixel, or adding a function to convert relative luminance to perceptual luminance just
        // for this line.
        boolean wallpaperIsDark = criticalRelativeLuminance < 19;

            // Apply composite colors where the foreground is a black layer with an alpha value of
            // the dim amount and the background is the wallpaper pixel color.
            int compositeColors = ColorUtils.compositeColors(blackTransparent, pixelColor);

            // Calculate the adjusted luminance of the dimmed wallpaper pixel color.
            double adjustedLuminance = ColorUtils.calculateLuminance(compositeColors);

            // Make sure we don't have a dark pixel mass that will
            // make text illegible.
            final boolean satisfiesTextContrast = ContrastColorUtil
                    .calculateContrast(pixelColor, Color.BLACK) > DARK_PIXEL_CONTRAST;
            if (!satisfiesTextContrast && alpha != 0) {
                darkPixels++;
                if (DEBUG_DARK_PIXELS) {
                    pixels[i] = Color.RED;
                }
            }
            totalLuminance += adjustedLuminance;
        }

        int hints = 0;
        hints |= wallpaperIsDark ? HINT_SUPPORTS_DARK_THEME : HINT_SUPPORTS_DARK_TEXT;
        double meanLuminance = totalLuminance / pixels.length;
        if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels < maxDarkPixels) {
            hints |= HINT_SUPPORTS_DARK_TEXT;
        }
        if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) {
            hints |= HINT_SUPPORTS_DARK_THEME;
        }

        if (DEBUG_DARK_PIXELS) {
            try (FileOutputStream out = new FileOutputStream("/data/pixels.png")) {
@@ -605,8 +592,8 @@ public final class WallpaperColors implements Parcelable {
            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.d("WallpaperColors", "median relative L: " + criticalRelativeLuminance
                    + ", numPixels: " + pixels.length);
            Log.d("WallpaperColors", "l: " + meanLuminance + ", d: " + darkPixels +
                    " maxD: " + maxDarkPixels + " numPixels: " + pixels.length);
        }

        return hints;
Loading