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

Commit 4eb6f77e authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Log the cached app high watermark" into udc-dev

parents 53c8ac6f af0e3535
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.os.TransactionTooLargeException;
import android.os.WorkSource;
import android.util.ArraySet;
import android.util.Pair;
import android.util.StatsEvent;

import com.android.internal.os.TimeoutRecord;

@@ -1217,4 +1218,10 @@ public abstract class ActivityManagerInternal {
     */
    public abstract void notifyMediaProjectionEvent(int uid, @NonNull IBinder projectionToken,
            @MediaProjectionTokenEvent int event);

    /**
     * @return The stats event for the cached apps high watermark since last pull.
     */
    @NonNull
    public abstract StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull);
}
+256 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.internal.util;

import android.annotation.NonNull;
import android.annotation.Nullable;

import java.util.Comparator;
import java.util.List;

/**
 * An implementation of the quick selection algorithm as described in
 * http://en.wikipedia.org/wiki/Quickselect.
 *
 * @hide
 */
public final class QuickSelect {
    private static <T> int selectImpl(@NonNull List<T> list, int left, int right, int k,
            @NonNull Comparator<? super T> comparator) {
        while (true) {
            if (left == right) {
                return left;
            }
            final int pivotIndex = partition(list, left, right, (left + right) >> 1, comparator);
            if (k == pivotIndex) {
                return k;
            } else if (k < pivotIndex) {
                right = pivotIndex - 1;
            } else {
                left = pivotIndex + 1;
            }
        }
    }

    private static int selectImpl(@NonNull int[] array, int left, int right, int k) {
        while (true) {
            if (left == right) {
                return left;
            }
            final int pivotIndex = partition(array, left, right, (left + right) >> 1);
            if (k == pivotIndex) {
                return k;
            } else if (k < pivotIndex) {
                right = pivotIndex - 1;
            } else {
                left = pivotIndex + 1;
            }
        }
    }

    private static int selectImpl(@NonNull long[] array, int left, int right, int k) {
        while (true) {
            if (left == right) {
                return left;
            }
            final int pivotIndex = partition(array, left, right, (left + right) >> 1);
            if (k == pivotIndex) {
                return k;
            } else if (k < pivotIndex) {
                right = pivotIndex - 1;
            } else {
                left = pivotIndex + 1;
            }
        }
    }

    private static <T> int selectImpl(@NonNull T[] array, int left, int right, int k,
            @NonNull Comparator<? super T> comparator) {
        while (true) {
            if (left == right) {
                return left;
            }
            final int pivotIndex = partition(array, left, right, (left + right) >> 1, comparator);
            if (k == pivotIndex) {
                return k;
            } else if (k < pivotIndex) {
                right = pivotIndex - 1;
            } else {
                left = pivotIndex + 1;
            }
        }
    }

    private static <T> int partition(@NonNull List<T> list, int left, int right, int pivotIndex,
            @NonNull Comparator<? super T> comparator) {
        final T pivotValue = list.get(pivotIndex);
        swap(list, right, pivotIndex);
        int storeIndex = left;
        for (int i = left; i < right; i++) {
            if (comparator.compare(list.get(i), pivotValue) < 0) {
                swap(list, storeIndex, i);
                storeIndex++;
            }
        }
        swap(list, right, storeIndex);
        return storeIndex;
    }

    private static int partition(@NonNull int[] array, int left, int right, int pivotIndex) {
        final int pivotValue = array[pivotIndex];
        swap(array, right, pivotIndex);
        int storeIndex = left;
        for (int i = left; i < right; i++) {
            if (array[i] < pivotValue) {
                swap(array, storeIndex, i);
                storeIndex++;
            }
        }
        swap(array, right, storeIndex);
        return storeIndex;
    }

    private static int partition(@NonNull long[] array, int left, int right, int pivotIndex) {
        final long pivotValue = array[pivotIndex];
        swap(array, right, pivotIndex);
        int storeIndex = left;
        for (int i = left; i < right; i++) {
            if (array[i] < pivotValue) {
                swap(array, storeIndex, i);
                storeIndex++;
            }
        }
        swap(array, right, storeIndex);
        return storeIndex;
    }

    private static <T> int partition(@NonNull T[] array, int left, int right, int pivotIndex,
            @NonNull Comparator<? super T> comparator) {
        final T pivotValue = array[pivotIndex];
        swap(array, right, pivotIndex);
        int storeIndex = left;
        for (int i = left; i < right; i++) {
            if (comparator.compare(array[i], pivotValue) < 0) {
                swap(array, storeIndex, i);
                storeIndex++;
            }
        }
        swap(array, right, storeIndex);
        return storeIndex;
    }

    private static <T> void swap(@NonNull List<T> list, int left, int right) {
        final T tmp = list.get(left);
        list.set(left, list.get(right));
        list.set(right, tmp);
    }

    private static void swap(@NonNull int[] array, int left, int right) {
        final int tmp = array[left];
        array[left] = array[right];
        array[right] = tmp;
    }

    private static void swap(@NonNull long[] array, int left, int right) {
        final long tmp = array[left];
        array[left] = array[right];
        array[right] = tmp;
    }

    private static <T> void swap(@NonNull T[] array, int left, int right) {
        final T tmp = array[left];
        array[left] = array[right];
        array[right] = tmp;
    }

    /**
     * Return the kth(0-based) smallest element from the given unsorted list.
     *
     * @param list The input list, it <b>will</b> be modified by the algorithm here.
     * @param start The start offset of the list, inclusive.
     * @param length The length of the sub list to be searched in.
     * @param k The 0-based index.
     * @param comparator The comparator which knows how to compare the elements in the list.
     * @return The kth smallest element from the given list,
     *         or IllegalArgumentException will be thrown if not found.
     */
    @Nullable
    public static <T> T select(@NonNull List<T> list, int start, int length, int k,
            @NonNull Comparator<? super T> comparator) {
        if (list == null || start < 0 || length <= 0 || list.size() < start + length
                || k < 0 || length <= k) {
            throw new IllegalArgumentException();
        }
        return list.get(selectImpl(list, start, start + length - 1, k + start, comparator));
    }

    /**
     * Return the kth(0-based) smallest element from the given unsorted array.
     *
     * @param array The input array, it <b>will</b> be modified by the algorithm here.
     * @param start The start offset of the array, inclusive.
     * @param length The length of the sub array to be searched in.
     * @param k The 0-based index to search for.
     * @return The kth smallest element from the given array,
     *         or IllegalArgumentException will be thrown if not found.
     */
    public static int select(@NonNull int[] array, int start, int length, int k) {
        if (array == null || start < 0 || length <= 0 || array.length < start + length
                || k < 0 || length <= k) {
            throw new IllegalArgumentException();
        }
        return array[selectImpl(array, start, start + length - 1, k + start)];
    }

    /**
     * Return the kth(0-based) smallest element from the given unsorted array.
     *
     * @param array The input array, it <b>will</b> be modified by the algorithm here.
     * @param start The start offset of the array, inclusive.
     * @param length The length of the sub array to be searched in.
     * @param k The 0-based index to search for.
     * @return The kth smallest element from the given array,
     *         or IllegalArgumentException will be thrown if not found.
     */
    public static long select(@NonNull long[] array, int start, int length, int k) {
        if (array == null || start < 0 || length <= 0 || array.length < start + length
                || k < 0 || length <= k) {
            throw new IllegalArgumentException();
        }
        return array[selectImpl(array, start, start + length - 1, k + start)];
    }

    /**
     * Return the kth(0-based) smallest element from the given unsorted array.
     *
     * @param array The input array, it <b>will</b> be modified by the algorithm here.
     * @param start The start offset of the array, inclusive.
     * @param length The length of the sub array to be searched in.
     * @param k The 0-based index to search for.
     * @param comparator The comparator which knows how to compare the elements in the list.
     * @return The kth smallest element from the given array,
     *         or IllegalArgumentException will be thrown if not found.
     */
    public static <T> T select(@NonNull T[] array, int start, int length, int k,
            @NonNull Comparator<? super T> comparator) {
        if (array == null || start < 0 || length <= 0 || array.length < start + length
                || k < 0 || length <= k) {
            throw new IllegalArgumentException();
        }
        return array[selectImpl(array, start, start + length - 1, k + start, comparator)];
    }
}
+152 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.internal.util;

import junit.framework.TestCase;

import java.util.Arrays;
import java.util.List;

/**
 * Tests for {@link QuickSelect}.
 */
public final class QuickSelectTest extends TestCase {

    public void testQuickSelect() throws Exception {
        test((List<Integer>) null, 0, null);
        test(Arrays.asList(), -1, null);
        test(Arrays.asList(), 0, null);
        test(Arrays.asList(), 1, null);
        test(Arrays.asList(1), -1, 1, 0, null);
        test(Arrays.asList(1), 1, -1, 0, null);
        test(Arrays.asList(1), 0, 1, -1, null);
        test(Arrays.asList(1), 1, 1, 0, null);
        test(Arrays.asList(1), 0, 1);
        test(Arrays.asList(1), 1, null);
        test(Arrays.asList(1, 2, 3, 4, 5), 0, 1);
        test(Arrays.asList(1, 2, 3, 4, 5), 1, 2);
        test(Arrays.asList(1, 2, 3, 4, 5), 2, 3);
        test(Arrays.asList(1, 2, 3, 4, 5), 3, 4);
        test(Arrays.asList(1, 2, 3, 4, 5), 4, 5);
        test(Arrays.asList(1, 2, 3, 4, 5), 5, null);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 2, 7);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 4, 9);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 7, 20);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 8, null);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 0, 3);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 1, 4);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 2, 10);
        test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 3, null);

        test((int[]) null, 0, null);
        test(new int[0], -1, null);
        test(new int[0], 0, null);
        test(new int[0], 1, null);
        test(new int[] {1}, -1, 1, 0, null);
        test(new int[] {1}, 1, -1, 0, null);
        test(new int[] {1}, 1, 0, -1, null);
        test(new int[] {1}, 1, 1, 0, null);
        test(new int[] {1}, 0, 1);
        test(new int[] {1}, 1, null);
        test(new int[] {1, 2, 3, 4, 5}, 0, 1);
        test(new int[] {1, 2, 3, 4, 5}, 1, 2);
        test(new int[] {1, 2, 3, 4, 5}, 2, 3);
        test(new int[] {1, 2, 3, 4, 5}, 3, 4);
        test(new int[] {1, 2, 3, 4, 5}, 4, 5);
        test(new int[] {1, 2, 3, 4, 5}, 5, null);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 2, 7);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 4, 9);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 7, 20);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 8, null);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 0, 3);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 1, 4);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 2, 10);
        test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 3, null);

        test((long[]) null, 0, null);
        test(new long[0], -1, null);
        test(new long[0], 0, null);
        test(new long[0], 1, null);
        test(new long[] {1}, -1, 1, 0, null);
        test(new long[] {1}, 1, -1, 0, null);
        test(new long[] {1}, 1, 0, -1, null);
        test(new long[] {1}, 1, 1, 0, null);
        test(new long[] {1}, 0, 1L);
        test(new long[] {1}, 1, null);
        test(new long[] {1, 2, 3, 4, 5}, 0, 1L);
        test(new long[] {1, 2, 3, 4, 5}, 1, 2L);
        test(new long[] {1, 2, 3, 4, 5}, 2, 3L);
        test(new long[] {1, 2, 3, 4, 5}, 3, 4L);
        test(new long[] {1, 2, 3, 4, 5}, 4, 5L);
        test(new long[] {1, 2, 3, 4, 5}, 5, null);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 2, 7L);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 4, 9L);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 7, 20L);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 8, null);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 0, 3L);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 1, 4L);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 2, 10L);
        test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 3, null);
    }

    private void test(List<Integer> input, int k, Integer expected) throws Exception {
        test(input, 0, input == null ? 0 : input.size(), k, expected);
    }

    private void test(List<Integer> input, int start, int length, int k, Integer expected)
            throws Exception {
        try {
            final Integer result = QuickSelect.select(input, start, length, k, Integer::compare);
            assertEquals(expected, result);
        } catch (IllegalArgumentException e) {
            if (expected != null) {
                throw new Exception(e);
            }
        }
    }

    private void test(int[] input, int k, Integer expected) throws Exception {
        test(input, 0, input == null ? 0 : input.length, k, expected);
    }

    private void test(int[] input, int start, int length, int k, Integer expected)
            throws Exception {
        try {
            final int result = QuickSelect.select(input, start, length, k);
            assertEquals((int) expected, result);
        } catch (IllegalArgumentException e) {
            if (expected != null) {
                throw new Exception(e);
            }
        }
    }

    private void test(long[] input, int k, Long expected) throws Exception {
        test(input, 0, input == null ? 0 : input.length, k, expected);
    }

    private void test(long[] input, int start, int length, int k, Long expected) throws Exception {
        try {
            final long result = QuickSelect.select(input, start, length, k);
            assertEquals((long) expected, result);
        } catch (IllegalArgumentException e) {
            if (expected != null) {
                throw new Exception(e);
            }
        }
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -382,6 +382,7 @@ import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.StatsEvent;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
@@ -1595,6 +1596,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    static final int SERVICE_SHORT_FGS_TIMEOUT_MSG = 76;
    static final int SERVICE_SHORT_FGS_PROCSTATE_TIMEOUT_MSG = 77;
    static final int SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG = 78;
    static final int UPDATE_CACHED_APP_HIGH_WATERMARK = 79;
    static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1938,6 +1940,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                case SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG: {
                    mServices.onShortFgsAnrTimeout((ServiceRecord) msg.obj);
                } break;
                case UPDATE_CACHED_APP_HIGH_WATERMARK: {
                    mAppProfiler.mCachedAppsWatermarkData.updateCachedAppsSnapshot((long) msg.obj);
                } break;
            }
        }
    }
@@ -18598,6 +18603,13 @@ public class ActivityManagerService extends IActivityManager.Stub
                @MediaProjectionTokenEvent int event) {
            ActivityManagerService.this.notifyMediaProjectionEvent(uid, projectionToken, event);
        }
        @Override
        @NonNull
        public StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull) {
            return mAppProfiler.mCachedAppsWatermarkData.getCachedAppsHighWatermarkStats(
                    atomTag, resetAfterPull);
        }
    }
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) {
+198 −4

File changed.

Preview size limit exceeded, changes collapsed.

Loading