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

Commit 0d60b075 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I0e61db91,Icb7ab995 into main

* changes:
  Revert "Update the BackgroundThread dependency"
  Revert "Utils required for CrashRecovery module"
parents 8a8fa607 1df0ae18
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -39,15 +39,15 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.LongArrayQueue;
import android.util.Slog;
import android.util.Xml;
import android.utils.BackgroundThread;
import android.utils.LongArrayQueue;
import android.utils.XmlUtils;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;

+2 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.content.pm.VersionedPackage;
import android.crashrecovery.flags.Flags;
import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.os.PowerManager;
import android.os.RecoverySystem;
import android.os.SystemClock;
@@ -43,11 +44,10 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.utils.ArrayUtils;
import android.utils.FileUtils;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
+0 −115
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.utils;

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

import java.io.File;
import java.util.List;
import java.util.Objects;

/**
 * Copied over from frameworks/base/core/java/com/android/internal/util/ArrayUtils.java
 *
 * @hide
 */
public class ArrayUtils {
    private ArrayUtils() { /* cannot be instantiated */ }
    public static final File[] EMPTY_FILE = new File[0];


    /**
     * Return first index of {@code value} in {@code array}, or {@code -1} if
     * not found.
     */
    public static <T> int indexOf(@Nullable T[] array, T value) {
        if (array == null) return -1;
        for (int i = 0; i < array.length; i++) {
            if (Objects.equals(array[i], value)) return i;
        }
        return -1;
    }

    /** @hide */
    public static @NonNull File[] defeatNullable(@Nullable File[] val) {
        return (val != null) ? val : EMPTY_FILE;
    }

    /**
     * Checks if given array is null or has zero elements.
     */
    public static boolean isEmpty(@Nullable int[] array) {
        return array == null || array.length == 0;
    }

    /**
     * True if the byte array is null or has length 0.
     */
    public static boolean isEmpty(@Nullable byte[] array) {
        return array == null || array.length == 0;
    }

    /**
     * Converts from List of bytes to byte array
     * @param list
     * @return byte[]
     */
    public static byte[] toPrimitive(List<byte[]> list) {
        if (list.size() == 0) {
            return new byte[0];
        }
        int byteLen = list.get(0).length;
        byte[] array = new byte[list.size() * byteLen];
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.get(i).length; j++) {
                array[i * byteLen + j] = list.get(i)[j];
            }
        }
        return array;
    }

    /**
     * Adds value to given array if not already present, providing set-like
     * behavior.
     */
    public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
        return appendInt(cur, val, false);
    }

    /**
     * Adds value to given array.
     */
    public static @NonNull int[] appendInt(@Nullable int[] cur, int val,
            boolean allowDuplicates) {
        if (cur == null) {
            return new int[] { val };
        }
        final int n = cur.length;
        if (!allowDuplicates) {
            for (int i = 0; i < n; i++) {
                if (cur[i] == val) {
                    return cur;
                }
            }
        }
        int[] ret = new int[n + 1];
        System.arraycopy(cur, 0, ret, 0, n);
        ret[n] = val;
        return ret;
    }
}
+0 −103
Original line number Diff line number Diff line
/*
 *  * Copyright (C) 2024 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 android.utils;

import android.annotation.NonNull;
import android.os.Handler;
import android.os.HandlerThread;

import com.android.internal.annotations.GuardedBy;

import java.util.concurrent.Executor;

/**
 * Thread for asynchronous event processing. This thread is configured as
 * {@link android.os.Process#THREAD_PRIORITY_BACKGROUND}, which means fewer CPU
 * resources will be dedicated to it, and it will "have less chance of impacting
 * the responsiveness of the user interface."
 * <p>
 * This thread is best suited for tasks that the user is not actively waiting
 * for, or for tasks that the user expects to be executed eventually.
 *
 * @see com.android.internal.os.BackgroundThread
 *
 * TODO: b/326916057 depend on modules-utils-backgroundthread instead
 * @hide
 */
public final class BackgroundThread extends HandlerThread {
    private static final Object sLock = new Object();

    @GuardedBy("sLock")
    private static BackgroundThread sInstance;
    @GuardedBy("sLock")
    private static Handler sHandler;
    @GuardedBy("sLock")
    private static HandlerExecutor sHandlerExecutor;

    private BackgroundThread() {
        super(BackgroundThread.class.getName(), android.os.Process.THREAD_PRIORITY_BACKGROUND);
    }

    @GuardedBy("sLock")
    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new BackgroundThread();
            sInstance.start();
            sHandler = new Handler(sInstance.getLooper());
            sHandlerExecutor = new HandlerExecutor(sHandler);
        }
    }

    /**
     * Get the singleton instance of this class.
     *
     * @return the singleton instance of this class
     */
    @NonNull
    public static BackgroundThread get() {
        synchronized (sLock) {
            ensureThreadLocked();
            return sInstance;
        }
    }

    /**
     * Get the singleton {@link Handler} for this class.
     *
     * @return the singleton {@link Handler} for this class.
     */
    @NonNull
    public static Handler getHandler() {
        synchronized (sLock) {
            ensureThreadLocked();
            return sHandler;
        }
    }

    /**
     * Get the singleton {@link Executor} for this class.
     *
     * @return the singleton {@link Executor} for this class.
     */
    @NonNull
    public static Executor getExecutor() {
        synchronized (sLock) {
            ensureThreadLocked();
            return sHandlerExecutor;
        }
    }
}
+0 −128
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.utils;

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

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Bits and pieces copied from hidden API of android.os.FileUtils.
 *
 * @hide
 */
public class FileUtils {
    /**
     * Read a text file into a String, optionally limiting the length.
     *
     * @param file     to read (will not seek, so things like /proc files are OK)
     * @param max      length (positive for head, negative of tail, 0 for no limit)
     * @param ellipsis to add of the file was truncated (can be null)
     * @return the contents of the file, possibly truncated
     * @throws IOException if something goes wrong reading the file
     * @hide
     */
    public static @Nullable String readTextFile(@Nullable File file, @Nullable int max,
            @Nullable String ellipsis) throws IOException {
        InputStream input = new FileInputStream(file);
        // wrapping a BufferedInputStream around it because when reading /proc with unbuffered
        // input stream, bytes read not equal to buffer size is not necessarily the correct
        // indication for EOF; but it is true for BufferedInputStream due to its implementation.
        BufferedInputStream bis = new BufferedInputStream(input);
        try {
            long size = file.length();
            if (max > 0 || (size > 0 && max == 0)) {  // "head" mode: read the first N bytes
                if (size > 0 && (max == 0 || size < max)) max = (int) size;
                byte[] data = new byte[max + 1];
                int length = bis.read(data);
                if (length <= 0) return "";
                if (length <= max) return new String(data, 0, length);
                if (ellipsis == null) return new String(data, 0, max);
                return new String(data, 0, max) + ellipsis;
            } else if (max < 0) {  // "tail" mode: keep the last N
                int len;
                boolean rolled = false;
                byte[] last = null;
                byte[] data = null;
                do {
                    if (last != null) rolled = true;
                    byte[] tmp = last;
                    last = data;
                    data = tmp;
                    if (data == null) data = new byte[-max];
                    len = bis.read(data);
                } while (len == data.length);

                if (last == null && len <= 0) return "";
                if (last == null) return new String(data, 0, len);
                if (len > 0) {
                    rolled = true;
                    System.arraycopy(last, len, last, 0, last.length - len);
                    System.arraycopy(data, 0, last, last.length - len, len);
                }
                if (ellipsis == null || !rolled) return new String(last);
                return ellipsis + new String(last);
            } else {  // "cat" mode: size unknown, read it all in streaming fashion
                ByteArrayOutputStream contents = new ByteArrayOutputStream();
                int len;
                byte[] data = new byte[1024];
                do {
                    len = bis.read(data);
                    if (len > 0) contents.write(data, 0, len);
                } while (len == data.length);
                return contents.toString();
            }
        } finally {
            bis.close();
            input.close();
        }
    }

    /**
     * Perform an fsync on the given FileOutputStream. The stream at this
     * point must be flushed but not yet closed.
     *
     * @hide
     */
    public static boolean sync(FileOutputStream stream) {
        try {
            if (stream != null) {
                stream.getFD().sync();
            }
            return true;
        } catch (IOException e) {
        }
        return false;
    }

    /**
     * List the files in the directory or return empty file.
     *
     * @hide
     */
    public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {
        return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles())
            : ArrayUtils.EMPTY_FILE;
    }
}
Loading