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

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

Snap for 7608384 from edb6d7f8 to sc-release

Change-Id: Icce24471d487efb8525dfa0f2bd9227048d68e45
parents b3abfad7 edb6d7f8
Loading
Loading
Loading
Loading
+160 −103
Original line number Diff line number Diff line
@@ -2849,14 +2849,14 @@ public class AppOpsManager {
    private static final ThreadLocal<Integer> sBinderThreadCallingUid = new ThreadLocal<>();

    /**
     * If a thread is currently executing a two-way binder transaction, this stores the
     * ops that were noted blaming any app (the caller, the caller of the caller, etc).
     * If a thread is currently executing a two-way binder transaction, this stores the op-codes of
     * the app-ops that were noted during this transaction.
     *
     * @see #getNotedOpCollectionMode
     * @see #collectNotedOpSync
     */
    private static final ThreadLocal<ArrayMap<String, ArrayMap<String, long[]>>>
            sAppOpsNotedInThisBinderTransaction = new ThreadLocal<>();
    private static final ThreadLocal<ArrayMap<String, long[]>> sAppOpsNotedInThisBinderTransaction =
            new ThreadLocal<>();

    /** Whether noting for an appop should be collected */
    private static final @ShouldCollectNoteOp byte[] sAppOpsToNote = new byte[_NUM_OP];
@@ -7205,6 +7205,34 @@ public class AppOpsManager {
     * @hide
     */
    public interface OnOpStartedListener {

        /**
         * Represents a start operation that was unsuccessful
         * @hide
         */
        public int START_TYPE_FAILED = 0;

        /**
         * Represents a successful start operation
         * @hide
         */
        public int START_TYPE_STARTED = 1;

        /**
         * Represents an operation where a restricted operation became unrestricted, and resumed.
         * @hide
         */
        public int START_TYPE_RESUMED = 2;

        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(flag = true, prefix = { "TYPE_" }, value = {
            START_TYPE_FAILED,
            START_TYPE_STARTED,
            START_TYPE_RESUMED
        })
        public @interface StartedType {}

        /**
         * Called when an op was started.
         *
@@ -7213,11 +7241,35 @@ public class AppOpsManager {
         * @param uid The UID performing the operation.
         * @param packageName The package performing the operation.
         * @param attributionTag The attribution tag performing the operation.
         * @param flags The flags of this op
         * @param flags The flags of this op.
         * @param result The result of the start.
         */
        void onOpStarted(int op, int uid, String packageName, String attributionTag,
                @OpFlags int flags, @Mode int result);

        /**
         * Called when an op was started.
         *
         * Note: This is only for op starts. It is not called when an op is noted or stopped.
         * By default, unless this method is overridden, no code will be executed for resume
         * events.
         * @param op The op code.
         * @param uid The UID performing the operation.
         * @param packageName The package performing the operation.
         * @param attributionTag The attribution tag performing the operation.
         * @param flags The flags of this op.
         * @param result The result of the start.
         * @param startType The start type of this start event. Either failed, resumed, or started.
         * @param attributionFlags The location of this started op in an attribution chain.
         * @param attributionChainId The ID of the attribution chain of this op, if it is in one.
         */
        default void onOpStarted(int op, int uid, String packageName, String attributionTag,
                @OpFlags int flags, @Mode int result, @StartedType int startType,
                @AttributionFlags int attributionFlags, int attributionChainId) {
            if (startType != START_TYPE_RESUMED) {
                onOpStarted(op, uid, packageName, attributionTag, flags, result);
            }
        }
    }

    AppOpsManager(Context context, IAppOpsService service) {
@@ -7858,8 +7910,10 @@ public class AppOpsManager {
             cb = new IAppOpsStartedCallback.Stub() {
                 @Override
                 public void opStarted(int op, int uid, String packageName, String attributionTag,
                         int flags, int mode) {
                     callback.onOpStarted(op, uid, packageName, attributionTag, flags, mode);
                         int flags, int mode, int startType, int attributionFlags,
                         int attributionChainId) {
                     callback.onOpStarted(op, uid, packageName, attributionTag, flags, mode,
                             startType, attributionFlags, attributionChainId);
                 }
             };
             mStartedWatchers.put(callback, cb);
@@ -9051,6 +9105,66 @@ public class AppOpsManager {
        sBinderThreadCallingUid.set(callingUid);
    }

    /**
     * State of a temporarily paused noted app-ops collection.
     *
     * @see #pauseNotedAppOpsCollection()
     *
     * @hide
     */
    public static class PausedNotedAppOpsCollection {
        final int mUid;
        final @Nullable ArrayMap<String, long[]> mCollectedNotedAppOps;

        PausedNotedAppOpsCollection(int uid, @Nullable ArrayMap<String,
                long[]> collectedNotedAppOps) {
            mUid = uid;
            mCollectedNotedAppOps = collectedNotedAppOps;
        }
    }

    /**
     * Temporarily suspend collection of noted app-ops when binder-thread calls into the other
     * process. During such a call there might be call-backs coming back on the same thread which
     * should not be accounted to the current collection.
     *
     * @return a state needed to resume the collection
     *
     * @hide
     */
    public static @Nullable PausedNotedAppOpsCollection pauseNotedAppOpsCollection() {
        Integer previousUid = sBinderThreadCallingUid.get();
        if (previousUid != null) {
            ArrayMap<String, long[]> previousCollectedNotedAppOps =
                    sAppOpsNotedInThisBinderTransaction.get();

            sBinderThreadCallingUid.remove();
            sAppOpsNotedInThisBinderTransaction.remove();

            return new PausedNotedAppOpsCollection(previousUid, previousCollectedNotedAppOps);
        }

        return null;
    }

    /**
     * Resume a collection paused via {@link #pauseNotedAppOpsCollection}.
     *
     * @param prevCollection The state of the previous collection
     *
     * @hide
     */
    public static void resumeNotedAppOpsCollection(
            @Nullable PausedNotedAppOpsCollection prevCollection) {
        if (prevCollection != null) {
            sBinderThreadCallingUid.set(prevCollection.mUid);

            if (prevCollection.mCollectedNotedAppOps != null) {
                sAppOpsNotedInThisBinderTransaction.set(prevCollection.mCollectedNotedAppOps);
            }
        }
    }

    /**
     * Finish collection of noted appops on this thread.
     *
@@ -9091,47 +9205,26 @@ public class AppOpsManager {
     */
    @TestApi
    public static void collectNotedOpSync(@NonNull SyncNotedAppOp syncOp) {
        collectNotedOpSync(sOpStrToOp.get(syncOp.getOp()), syncOp.getAttributionTag(),
                syncOp.getPackageName());
    }

    /**
     * Collect a noted op when inside of a two-way binder call.
     *
     * <p> Delivered to caller via {@link #prefixParcelWithAppOpsIfNeeded}
     *
     * @param code the op code to note for
     * @param attributionTag the attribution tag to note for
     * @param packageName the package to note for
     */
    private static void collectNotedOpSync(int code, @Nullable String attributionTag,
            @NonNull String packageName) {
        // If this is inside of a two-way binder call:
        // We are inside of a two-way binder call. Delivered to caller via
        // {@link #prefixParcelWithAppOpsIfNeeded}
        ArrayMap<String, ArrayMap<String, long[]>> appOpsNoted =
                sAppOpsNotedInThisBinderTransaction.get();
        int op = sOpStrToOp.get(syncOp.getOp());
        ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
        if (appOpsNoted == null) {
            appOpsNoted = new ArrayMap<>(1);
            sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
        }

        ArrayMap<String, long[]> packageAppOpsNotedForAttribution = appOpsNoted.get(packageName);
        if (packageAppOpsNotedForAttribution == null) {
            packageAppOpsNotedForAttribution = new ArrayMap<>(1);
            appOpsNoted.put(packageName, packageAppOpsNotedForAttribution);
        }

        long[] appOpsNotedForAttribution = packageAppOpsNotedForAttribution.get(attributionTag);
        long[] appOpsNotedForAttribution = appOpsNoted.get(syncOp.getAttributionTag());
        if (appOpsNotedForAttribution == null) {
            appOpsNotedForAttribution = new long[2];
            packageAppOpsNotedForAttribution.put(attributionTag, appOpsNotedForAttribution);
            appOpsNoted.put(syncOp.getAttributionTag(), appOpsNotedForAttribution);
        }

        if (code < 64) {
            appOpsNotedForAttribution[0] |= 1L << code;
        if (op < 64) {
            appOpsNotedForAttribution[0] |= 1L << op;
        } else {
            appOpsNotedForAttribution[1] |= 1L << (code - 64);
            appOpsNotedForAttribution[1] |= 1L << (op - 64);
        }
    }

@@ -9185,7 +9278,9 @@ public class AppOpsManager {
            }
        }

        if (isListeningForOpNotedInBinderTransaction()) {
        Integer binderUid = sBinderThreadCallingUid.get();

        if (binderUid != null && binderUid == uid) {
            return COLLECT_SYNC;
        } else {
            return COLLECT_ASYNC;
@@ -9204,32 +9299,20 @@ public class AppOpsManager {
     */
    // TODO (b/186872903) Refactor how sync noted ops are propagated.
    public static void prefixParcelWithAppOpsIfNeeded(@NonNull Parcel p) {
        if (!isListeningForOpNotedInBinderTransaction()) {
            return;
        }
        final ArrayMap<String, ArrayMap<String, long[]>> notedAppOps =
                sAppOpsNotedInThisBinderTransaction.get();
        ArrayMap<String, long[]> notedAppOps = sAppOpsNotedInThisBinderTransaction.get();
        if (notedAppOps == null) {
            return;
        }

        p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);

        final int packageCount = notedAppOps.size();
        p.writeInt(packageCount);
        int numAttributionWithNotesAppOps = notedAppOps.size();
        p.writeInt(numAttributionWithNotesAppOps);

        for (int i = 0; i < packageCount; i++) {
        for (int i = 0; i < numAttributionWithNotesAppOps; i++) {
            p.writeString(notedAppOps.keyAt(i));

            final ArrayMap<String, long[]> notedTagAppOps = notedAppOps.valueAt(i);
            final int tagCount = notedTagAppOps.size();
            p.writeInt(tagCount);

            for (int j = 0; j < tagCount; j++) {
                p.writeString(notedTagAppOps.keyAt(j));
                p.writeLong(notedTagAppOps.valueAt(j)[0]);
                p.writeLong(notedTagAppOps.valueAt(j)[1]);
            }
            p.writeLong(notedAppOps.valueAt(i)[0]);
            p.writeLong(notedAppOps.valueAt(i)[1]);
        }
    }

@@ -9244,54 +9327,36 @@ public class AppOpsManager {
     * @hide
     */
    public static void readAndLogNotedAppops(@NonNull Parcel p) {
        final int packageCount = p.readInt();
        if (packageCount <= 0) {
            return;
        }
        int numAttributionsWithNotedAppOps = p.readInt();

        final String myPackageName = ActivityThread.currentPackageName();

        synchronized (sLock) {
            for (int i = 0; i < packageCount; i++) {
                final String packageName = p.readString();

                final int tagCount = p.readInt();
                for (int j = 0; j < tagCount; j++) {
                    final String attributionTag = p.readString();
                    final long[] rawNotedAppOps = new long[2];
        for (int i = 0; i < numAttributionsWithNotedAppOps; i++) {
            String attributionTag = p.readString();
            long[] rawNotedAppOps = new long[2];
            rawNotedAppOps[0] = p.readLong();
            rawNotedAppOps[1] = p.readLong();

                    if (rawNotedAppOps[0] == 0 && rawNotedAppOps[1] == 0) {
                        continue;
                    }
            if (rawNotedAppOps[0] != 0 || rawNotedAppOps[1] != 0) {
                BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);

                    final BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
                synchronized (sLock) {
                    for (int code = notedAppOps.nextSetBit(0); code != -1;
                            code = notedAppOps.nextSetBit(code + 1)) {
                        if (Objects.equals(myPackageName, packageName)) {
                        if (sOnOpNotedCallback != null) {
                                sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code,
                                        attributionTag, packageName));
                            sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, attributionTag));
                        } else {
                            String message = getFormattedStackTrace();
                                sUnforwardedOps.add(new AsyncNotedAppOp(code, Process.myUid(),
                                        attributionTag, message, System.currentTimeMillis()));
                            sUnforwardedOps.add(
                                    new AsyncNotedAppOp(code, Process.myUid(), attributionTag,
                                            message, System.currentTimeMillis()));
                            if (sUnforwardedOps.size() > MAX_UNFORWARDED_OPS) {
                                sUnforwardedOps.remove(0);
                            }
                        }
                        } else if (isListeningForOpNotedInBinderTransaction()) {
                            collectNotedOpSync(code, attributionTag, packageName);
                    }
                }
                for (int code = notedAppOps.nextSetBit(0); code != -1;
                        code = notedAppOps.nextSetBit(code + 1)) {
                        if (Objects.equals(myPackageName, packageName)) {
                            sMessageCollector.onNoted(new SyncNotedAppOp(code,
                                    attributionTag, packageName));
                        }
                    }
                    sMessageCollector.onNoted(new SyncNotedAppOp(code, attributionTag));
                }
            }
        }
@@ -9398,15 +9463,7 @@ public class AppOpsManager {
     * @hide
     */
    public static boolean isListeningForOpNoted() {
        return sOnOpNotedCallback != null || isListeningForOpNotedInBinderTransaction()
                || isCollectingStackTraces();
    }

    /**
     * @return whether we are in a binder transaction and collecting appops.
     */
    private static boolean isListeningForOpNotedInBinderTransaction() {
        return sBinderThreadCallingUid.get() != null;
        return sOnOpNotedCallback != null || isCollectingStackTraces();
    }

    /**
+2 −1
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcelable;
import android.os.Process;

import com.android.internal.annotations.Immutable;
import com.android.internal.util.DataClass;
@@ -29,6 +28,8 @@ import com.android.internal.util.DataClass;
/**
 * Description of an app-op that was noted for the current process.
 *
 * Note: package name is currently unused in the system.
 *
 * <p>This is either delivered after a
 * {@link AppOpsManager.OnOpNotedCallback#onNoted(SyncNotedAppOp) two way binder call} or
 * when the app
+5 −0
Original line number Diff line number Diff line
@@ -560,6 +560,9 @@ public final class BinderProxy implements IBinder {
            }
        }

        final AppOpsManager.PausedNotedAppOpsCollection prevCollection =
                AppOpsManager.pauseNotedAppOpsCollection();

        if ((flags & FLAG_ONEWAY) == 0 && AppOpsManager.isListeningForOpNoted()) {
            flags |= FLAG_COLLECT_NOTED_APP_OPS;
        }
@@ -567,6 +570,8 @@ public final class BinderProxy implements IBinder {
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            AppOpsManager.resumeNotedAppOpsCollection(prevCollection);

            if (transactListener != null) {
                transactListener.onTransactEnded(session);
            }
+72 −12
Original line number Diff line number Diff line
@@ -31,7 +31,9 @@ import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE;
import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.media.AudioSystem.MODE_IN_COMMUNICATION;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;

@@ -63,7 +65,8 @@ import java.util.Objects;
 *
 * @hide
 */
public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedListener {
public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedListener,
        AppOpsManager.OnOpStartedListener {

    /** Whether to show the mic and camera icons.  */
    private static final String PROPERTY_CAMERA_MIC_ICONS_ENABLED = "camera_mic_icons_enabled";
@@ -160,9 +163,10 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
        mUserContexts = new ArrayMap<>();
        mUserContexts.put(Process.myUserHandle(), mContext);
        // TODO ntmyren: make this listen for flag enable/disable changes
        String[] ops = { OPSTR_CAMERA, OPSTR_RECORD_AUDIO };
        mContext.getSystemService(AppOpsManager.class).startWatchingActive(ops,
                context.getMainExecutor(), this);
        String[] opStrs = { OPSTR_CAMERA, OPSTR_RECORD_AUDIO };
        mAppOpsManager.startWatchingActive(opStrs, context.getMainExecutor(), this);
        int[] ops = { OP_CAMERA, OP_RECORD_AUDIO };
        mAppOpsManager.startWatchingStarted(ops, this);
    }

    private Context getUserContext(UserHandle user) {
@@ -182,25 +186,65 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
    public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
            @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags,
            int attributionChainId) {
        if (attributionChainId == ATTRIBUTION_CHAIN_ID_NONE
                || attributionFlags == ATTRIBUTION_FLAGS_NONE
                || (attributionFlags & ATTRIBUTION_FLAG_TRUSTED) == 0) {
            // If this is not a chain, or it is untrusted, return
        if (active) {
            // Started callback handles these
            return;
        }

        if (!active) {
            // if any link in the chain is finished, remove the chain.
        // if any link in the chain is finished, remove the chain. Then, find any other chains that
        // contain this op/package/uid/tag combination, and remove them, as well.
        // TODO ntmyren: be smarter about this
        mAttributionChains.remove(attributionChainId);
        int numChains = mAttributionChains.size();
        ArrayList<Integer> toRemove = new ArrayList<>();
        for (int i = 0; i < numChains; i++) {
            int chainId = mAttributionChains.keyAt(i);
            ArrayList<AccessChainLink> chain = mAttributionChains.valueAt(i);
            int chainSize = chain.size();
            for (int j = 0; j < chainSize; j++) {
                AccessChainLink link = chain.get(j);
                if (link.packageAndOpEquals(op, packageName, attributionTag, uid)) {
                    toRemove.add(chainId);
                    break;
                }
            }
        }
        mAttributionChains.removeAll(toRemove);
    }

    @Override
    public void onOpStarted(int op, int uid, String packageName, String attributionTag,
                @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
       // not part of an attribution chain. Do nothing
    }

    @Override
    public void onOpStarted(int op, int uid, String packageName, String attributionTag,
            @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result,
            @StartedType int startedType, @AttributionFlags int attributionFlags,
            int attributionChainId) {
        if (startedType == START_TYPE_FAILED || attributionChainId == ATTRIBUTION_CHAIN_ID_NONE
                || attributionFlags == ATTRIBUTION_FLAGS_NONE
                || (attributionFlags & ATTRIBUTION_FLAG_TRUSTED) == 0) {
            // If this is not a successful start, or it is not a chain, or it is untrusted, return
            return;
        }
        addLinkToChainIfNotPresent(AppOpsManager.opToPublicName(op), packageName, uid,
                attributionTag, attributionFlags, attributionChainId);
    }

    private void addLinkToChainIfNotPresent(String op, String packageName, int uid,
            String attributionTag, int attributionFlags, int attributionChainId) {

        ArrayList<AccessChainLink> currentChain = mAttributionChains.computeIfAbsent(
                attributionChainId, k -> new ArrayList<>());
        AccessChainLink link = new AccessChainLink(op, packageName, attributionTag, uid,
                attributionFlags);

        if (currentChain.contains(link)) {
            return;
        }

        int currSize = currentChain.size();
        if (currSize == 0 || link.isEnd() || !currentChain.get(currSize - 1).isEnd()) {
            // if the list is empty, this link is the end, or the last link in the current chain
@@ -613,5 +657,21 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
        public boolean isStart() {
            return (flags & ATTRIBUTION_FLAG_RECEIVER) != 0;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof AccessChainLink)) {
                return false;
            }
            AccessChainLink other = (AccessChainLink) obj;
            return other.flags == flags && packageAndOpEquals(other.usage.op,
                    other.usage.packageName, other.usage.attributionTag, other.usage.uid);
        }

        public boolean packageAndOpEquals(String op, String packageName, String attributionTag,
                int uid) {
            return Objects.equals(op, usage.op) && Objects.equals(packageName, usage.packageName)
                    && Objects.equals(attributionTag, usage.attributionTag) && uid == usage.uid;
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -1242,7 +1242,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            mBlastSurfaceControl.setTransformHint(mTransformHint);
            if (mBlastBufferQueue != null) {
                mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight,
                        mFormat);
                        mFormat, transaction);
            }
        } else {
            transaction.setBufferSize(mSurfaceControl, mSurfaceWidth, mSurfaceHeight);
Loading