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

Commit ae2f363d authored by /e/ robot's avatar /e/ robot
Browse files

Merge remote-tracking branch 'origin/lineage-20.0' into v1-t

parents 8f028d60 852a3628
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ public abstract class Context {
            BIND_IMPORTANT,
            BIND_ADJUST_WITH_ACTIVITY,
            BIND_NOT_PERCEPTIBLE,
            BIND_DENY_ACTIVITY_STARTS_PRE_34,
            BIND_INCLUDE_CAPABILITIES
    })
    @Retention(RetentionPolicy.SOURCE)
@@ -392,6 +393,14 @@ public abstract class Context {
    /***********    Public flags above this line ***********/
    /***********    Hidden flags below this line ***********/

    /**
     * Flag for {@link #bindService}: If binding from an app that is visible, the bound service is
     * allowed to start an activity from background. Add a flag so that this behavior can be opted
     * out.
     * @hide
     */
    public static final int BIND_DENY_ACTIVITY_STARTS_PRE_34 = 0X000004000;

    /**
     * Flag for {@link #bindService}: This flag is only intended to be used by the system to
     * indicate that a service binding is not considered as real package component usage and should
+7 −0
Original line number Diff line number Diff line
@@ -9581,6 +9581,13 @@ public final class Settings {
         */
        public static final String SPATIAL_AUDIO_ENABLED = "spatial_audio_enabled";
        /**
         * Internal collection of audio device inventory items
         * The device item stored are {@link com.android.server.audio.AdiDeviceState}
         * @hide
         */
        public static final String AUDIO_DEVICE_INVENTORY = "audio_device_inventory";
        /**
         * Indicates whether notification display on the lock screen is enabled.
         * <p>
+88 −78
Original line number Diff line number Diff line
@@ -62,14 +62,14 @@ import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import java.util.regex.Pattern;

/**
 * A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
@@ -87,6 +87,8 @@ public abstract class FileSystemProvider extends DocumentsProvider {
            DocumentsContract.QUERY_ARG_LAST_MODIFIED_AFTER,
            DocumentsContract.QUERY_ARG_MIME_TYPES);

    private static final int MAX_RESULTS_NUMBER = 23;

    private static String joinNewline(String... args) {
        return TextUtils.join("\n", args);
    }
@@ -373,62 +375,53 @@ public abstract class FileSystemProvider extends DocumentsProvider {
    }

    /**
     * This method is similar to
     * {@link DocumentsProvider#queryChildDocuments(String, String[], String)}. This method returns
     * all children documents including hidden directories/files.
     *
     * <p>
     * In a scoped storage world, access to "Android/data" style directories are hidden for privacy
     * reasons. This method may show privacy sensitive data, so its usage should only be in
     * restricted modes.
     *
     * @param parentDocumentId the directory to return children for.
     * @param projection list of {@link Document} columns to put into the
     *            cursor. If {@code null} all supported columns should be
     *            included.
     * @param sortOrder how to order the rows, formatted as an SQL
     *            {@code ORDER BY} clause (excluding the ORDER BY itself).
     *            Passing {@code null} will use the default sort order, which
     *            may be unordered. This ordering is a hint that can be used to
     *            prioritize how data is fetched from the network, but UI may
     *            always enforce a specific ordering
     * @throws FileNotFoundException when parent document doesn't exist or query fails
     * WARNING: this method should really be {@code final}, but for the backward compatibility it's
     * not; new classes that extend {@link FileSystemProvider} should override
     * {@link #queryChildDocuments(String, String[], String, boolean)}, not this method.
     */
    protected Cursor queryChildDocumentsShowAll(
            String parentDocumentId, String[] projection, String sortOrder)
    @Override
    public Cursor queryChildDocuments(String documentId, String[] projection, String sortOrder)
            throws FileNotFoundException {
        return queryChildDocuments(parentDocumentId, projection, sortOrder, File -> true);
        return queryChildDocuments(documentId, projection, sortOrder, /* includeHidden */ false);
    }

    /**
     * This method is similar to {@link #queryChildDocuments(String, String[], String)}, however, it
     * could return <b>all</b> content of the directory, <b>including restricted (hidden)
     * directories and files</b>.
     * <p>
     * In the scoped storage world, some directories and files (e.g. {@code Android/data/} and
     * {@code Android/obb/} on the external storage) are hidden for privacy reasons.
     * Hence, this method may reveal privacy-sensitive data, thus should be used with extra care.
     */
    @Override
    public Cursor queryChildDocuments(
            String parentDocumentId, String[] projection, String sortOrder)
            throws FileNotFoundException {
        // Access to some directories is hidden for privacy reasons.
        return queryChildDocuments(parentDocumentId, projection, sortOrder, this::shouldShow);
    public final Cursor queryChildDocumentsForManage(String documentId, String[] projection,
            String sortOrder) throws FileNotFoundException {
        return queryChildDocuments(documentId, projection, sortOrder, /* includeHidden */ true);
    }

    private Cursor queryChildDocuments(
            String parentDocumentId, String[] projection, String sortOrder,
            @NonNull Predicate<File> filter) throws FileNotFoundException {
        final File parent = getFileForDocId(parentDocumentId);
    protected Cursor queryChildDocuments(String documentId, String[] projection, String sortOrder,
            boolean includeHidden) throws FileNotFoundException {
        final File parent = getFileForDocId(documentId);
        final MatrixCursor result = new DirectoryCursor(
                resolveProjection(projection), parentDocumentId, parent);
                resolveProjection(projection), documentId, parent);

        if (!parent.isDirectory()) {
            Log.w(TAG, '"' + documentId + "\" is not a directory");
            return result;
        }

        if (!filter.test(parent)) {
            Log.w(TAG, "No permission to access parentDocumentId: " + parentDocumentId);
        if (!includeHidden && shouldHideDocument(documentId)) {
            Log.w(TAG, "Queried directory \"" + documentId + "\" is hidden");
            return result;
        }

        if (parent.isDirectory()) {
        for (File file : FileUtils.listFilesOrEmpty(parent)) {
                if (filter.test(file)) {
            if (!includeHidden && shouldHideDocument(file)) continue;

            includeFile(result, null, file);
        }
            }
        } else {
            Log.w(TAG, "parentDocumentId '" + parentDocumentId + "' is not Directory");
        }

        return result;
    }

@@ -450,23 +443,29 @@ public abstract class FileSystemProvider extends DocumentsProvider {
     *
     * @see ContentResolver#EXTRA_HONORED_ARGS
     */
    protected final Cursor querySearchDocuments(
            File folder, String[] projection, Set<String> exclusion, Bundle queryArgs)
            throws FileNotFoundException {
    protected final Cursor querySearchDocuments(File folder, String[] projection,
            Set<String> exclusion, Bundle queryArgs) throws FileNotFoundException {
        final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
        final LinkedList<File> pending = new LinkedList<>();
        pending.add(folder);
        while (!pending.isEmpty() && result.getCount() < 24) {
            final File file = pending.removeFirst();
            if (shouldHide(file)) continue;

        // We'll be a running a BFS here.
        final Queue<File> pending = new ArrayDeque<>();
        pending.offer(folder);

        while (!pending.isEmpty() && result.getCount() < MAX_RESULTS_NUMBER) {
            final File file = pending.poll();

            // Skip hidden documents (both files and directories)
            if (shouldHideDocument(file)) continue;

            if (file.isDirectory()) {
                for (File child : FileUtils.listFilesOrEmpty(file)) {
                    pending.add(child);
                    pending.offer(child);
                }
            }
            if (!exclusion.contains(file.getAbsolutePath()) && matchSearchQueryArguments(file,
                    queryArgs)) {

            if (exclusion.contains(file.getAbsolutePath())) continue;

            if (matchSearchQueryArguments(file, queryArgs)) {
                includeFile(result, null, file);
            }
        }
@@ -610,26 +609,23 @@ public abstract class FileSystemProvider extends DocumentsProvider {

        final int flagIndex = ArrayUtils.indexOf(columns, Document.COLUMN_FLAGS);
        if (flagIndex != -1) {
            final boolean isDir = mimeType.equals(Document.MIME_TYPE_DIR);
            int flags = 0;
            if (file.canWrite()) {
                if (mimeType.equals(Document.MIME_TYPE_DIR)) {
                    flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
                flags |= Document.FLAG_SUPPORTS_DELETE;
                flags |= Document.FLAG_SUPPORTS_RENAME;
                flags |= Document.FLAG_SUPPORTS_MOVE;

                    if (shouldBlockFromTree(docId)) {
                        flags |= Document.FLAG_DIR_BLOCKS_OPEN_DOCUMENT_TREE;
                    }

                if (isDir) {
                    flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
                } else {
                    flags |= Document.FLAG_SUPPORTS_WRITE;
                    flags |= Document.FLAG_SUPPORTS_DELETE;
                    flags |= Document.FLAG_SUPPORTS_RENAME;
                    flags |= Document.FLAG_SUPPORTS_MOVE;
                }
            }

            if (isDir && shouldBlockDirectoryFromTree(docId)) {
                flags |= Document.FLAG_DIR_BLOCKS_OPEN_DOCUMENT_TREE;
            }

            if (mimeType.startsWith("image/")) {
                flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
            }
@@ -662,22 +658,36 @@ public abstract class FileSystemProvider extends DocumentsProvider {
        return row;
    }

    private static final Pattern PATTERN_HIDDEN_PATH = Pattern.compile(
            "(?i)^/storage/[^/]+/(?:[0-9]+/)?Android/(?:data|obb|sandbox)$");

    /**
     * In a scoped storage world, access to "Android/data" style directories are
     * hidden for privacy reasons.
     * Some providers may want to restrict access to certain directories and files,
     * e.g. <i>"Android/data"</i> and <i>"Android/obb"</i> on the shared storage for
     * privacy reasons.
     * Such providers should override this method.
     */
    protected boolean shouldHide(@NonNull File file) {
        return (PATTERN_HIDDEN_PATH.matcher(file.getAbsolutePath()).matches());
    protected boolean shouldHideDocument(@NonNull String documentId)
            throws FileNotFoundException {
        return false;
    }

    private boolean shouldShow(@NonNull File file) {
        return !shouldHide(file);
    /**
     * A variant of the {@link #shouldHideDocument(String)} that takes a {@link File} instead of
     * a {@link String} {@code documentId}.
     *
     * @see #shouldHideDocument(String)
     */
    protected final boolean shouldHideDocument(@NonNull File document)
            throws FileNotFoundException {
        return shouldHideDocument(getDocIdForFile(document));
    }

    protected boolean shouldBlockFromTree(@NonNull String docId) {
    /**
     * @return if the directory that should be blocked from being selected when the user launches
     * an {@link Intent#ACTION_OPEN_DOCUMENT_TREE} intent.
     *
     * @see Document#FLAG_DIR_BLOCKS_OPEN_DOCUMENT_TREE
     */
    protected boolean shouldBlockDirectoryFromTree(@NonNull String documentId)
            throws FileNotFoundException {
        return false;
    }

+1 −0
Original line number Diff line number Diff line
@@ -524,6 +524,7 @@ message ConnectionRecordProto {
        DEAD = 15;
        NOT_PERCEPTIBLE = 16;
        INCLUDE_CAPABILITIES = 17;
        DENY_ACTIVITY_STARTS_PRE_34 = 18;
    }
    repeated Flag flags = 3;
    optional string service_name = 4;
+25 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ public final class AudioDeviceAttributes implements Parcelable {
    /**
     * The unique address of the device. Some devices don't have addresses, only an empty string.
     */
    private final @NonNull String mAddress;
    private @NonNull String mAddress;
    /**
     * The non-unique name of the device. Some devices don't have names, only an empty string.
     * Should not be used as a unique identifier for a device.
@@ -186,6 +186,21 @@ public final class AudioDeviceAttributes implements Parcelable {
        mAudioDescriptors = new ArrayList<>();
    }

    /**
     * @hide
     * Copy Constructor.
     * @param ada the copied AudioDeviceAttributes
     */
    public AudioDeviceAttributes(AudioDeviceAttributes ada) {
        mRole = ada.getRole();
        mType = ada.getType();
        mAddress = ada.getAddress();
        mName = ada.getName();
        mNativeType = ada.getInternalType();
        mAudioProfiles = ada.getAudioProfiles();
        mAudioDescriptors = ada.getAudioDescriptors();
    }

    /**
     * @hide
     * Returns the role of a device
@@ -216,6 +231,15 @@ public final class AudioDeviceAttributes implements Parcelable {
        return mAddress;
    }

    /**
     * @hide
     * Sets the device address. Only used by audio service.
     */
    public void setAddress(@NonNull String address) {
        Objects.requireNonNull(address);
        mAddress = address;
    }

    /**
     * @hide
     * Returns the name of the audio device, or an empty string for devices without one
Loading