/*
 * Copyright (C) 2020 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.permission;

import static android.Manifest.permission_group.CAMERA;
import static android.Manifest.permission_group.LOCATION;
import static android.Manifest.permission_group.MICROPHONE;
import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
import static android.app.AppOpsManager.ATTRIBUTION_FLAGS_NONE;
import static android.app.AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
import static android.app.AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
import static android.app.AppOpsManager.ATTRIBUTION_FLAG_TRUSTED;
import static android.app.AppOpsManager.AttributionFlags;
import static android.app.AppOpsManager.OPSTR_CAMERA;
import static android.app.AppOpsManager.OPSTR_COARSE_LOCATION;
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;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.icu.text.ListFormatter;
import android.media.AudioManager;
import android.os.Process;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * A helper which gets all apps which have used microphone, camera, and possible location
 * permissions within a certain timeframe, as well as possible special attributions, and if the
 * usage is a phone call.
 *
 * @hide
 */
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";

    /** Whether to show the location indicators. */
    private static final String PROPERTY_LOCATION_INDICATORS_ENABLED =
            "location_indicators_enabled";

    /** Whether to show the Permissions Hub.  */
    private static final String PROPERTY_PERMISSIONS_HUB_2_ENABLED = "permissions_hub_2_enabled";

    /** How long after an access to show it as "recent" */
    private static final String RECENT_ACCESS_TIME_MS = "recent_access_time_ms";

    /** How long after an access to show it as "running" */
    private static final String RUNNING_ACCESS_TIME_MS = "running_access_time_ms";

    private static final String SYSTEM_PKG = "android";

    private static final long DEFAULT_RUNNING_TIME_MS = 5000L;
    private static final long DEFAULT_RECENT_TIME_MS = 15000L;

    private static boolean shouldShowPermissionsHub() {
        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                PROPERTY_PERMISSIONS_HUB_2_ENABLED, false);
    }

    private static boolean shouldShowIndicators() {
        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                PROPERTY_CAMERA_MIC_ICONS_ENABLED, true) || shouldShowPermissionsHub();
    }

    private static boolean shouldShowLocationIndicator() {
        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                PROPERTY_LOCATION_INDICATORS_ENABLED, false);
    }

    private static long getRecentThreshold(Long now) {
        return now - DeviceConfig.getLong(DeviceConfig.NAMESPACE_PRIVACY,
                RECENT_ACCESS_TIME_MS, DEFAULT_RECENT_TIME_MS);
    }

    private static long getRunningThreshold(Long now) {
        return now - DeviceConfig.getLong(DeviceConfig.NAMESPACE_PRIVACY,
                RUNNING_ACCESS_TIME_MS, DEFAULT_RUNNING_TIME_MS);
    }

    private static final List<String> LOCATION_OPS = List.of(
            OPSTR_COARSE_LOCATION,
            OPSTR_FINE_LOCATION
    );

    private static final List<String> MIC_OPS = List.of(
            OPSTR_PHONE_CALL_MICROPHONE,
            OPSTR_RECORD_AUDIO
    );

    private static final List<String> CAMERA_OPS = List.of(
            OPSTR_PHONE_CALL_CAMERA,
            OPSTR_CAMERA
    );

    private static @NonNull String getGroupForOp(String op) {
        switch(op) {
            case OPSTR_RECORD_AUDIO:
                return MICROPHONE;
            case OPSTR_CAMERA:
                return CAMERA;
            case OPSTR_PHONE_CALL_MICROPHONE:
            case OPSTR_PHONE_CALL_CAMERA:
                return op;
            case OPSTR_COARSE_LOCATION:
            case OPSTR_FINE_LOCATION:
                return LOCATION;
            default:
                throw new IllegalArgumentException("Unknown app op: " + op);
        }
    }

    private Context mContext;
    private ArrayMap<UserHandle, Context> mUserContexts;
    private PackageManager mPkgManager;
    private AppOpsManager mAppOpsManager;
    private ArrayMap<Integer, ArrayList<AccessChainLink>> mAttributionChains = new ArrayMap<>();

    /**
     * Constructor for PermissionUsageHelper
     * @param context The context from which to derive the package information
     */
    public PermissionUsageHelper(@NonNull Context context) {
        mContext = context;
        mPkgManager = context.getPackageManager();
        mAppOpsManager = context.getSystemService(AppOpsManager.class);
        mUserContexts = new ArrayMap<>();
        mUserContexts.put(Process.myUserHandle(), mContext);
        // TODO ntmyren: make this listen for flag enable/disable changes
        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) {
        if (!(mUserContexts.containsKey(user))) {
            mUserContexts.put(user, mContext.createContextAsUser(user, 0));
        }
        return mUserContexts.get(user);
    }

    @Override
    public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
            boolean active) {
        // not part of an attribution chain. Do nothing
    }

    @Override
    public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
            @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags,
            int attributionChainId) {
        if (active) {
            // Started callback handles these
            return;
        }

        // 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
            // isn't the end, add it to the end
            currentChain.add(link);
        } else if (link.isStart()) {
            currentChain.add(0, link);
        } else if (currentChain.get(currentChain.size() - 1).isEnd()) {
            // we already have the end, and this is a mid node, so insert before the end
            currentChain.add(currSize - 1, link);
        }
    }

    /**
     * @see PermissionManager.getIndicatorAppOpUsageData
     */
    public @NonNull List<PermGroupUsage> getOpUsageData(boolean isMicMuted) {
        List<PermGroupUsage> usages = new ArrayList<>();

        if (!shouldShowIndicators()) {
            return usages;
        }

        List<String> ops = new ArrayList<>(CAMERA_OPS);
        if (shouldShowLocationIndicator()) {
            ops.addAll(LOCATION_OPS);
        }
        if (!isMicMuted) {
            ops.addAll(MIC_OPS);
        }

        Map<String, List<OpUsage>> rawUsages = getOpUsages(ops);

        ArrayList<String> usedPermGroups = new ArrayList<>(rawUsages.keySet());

        // If we have a phone call, and a carrier privileged app using microphone, hide the
        // phone call.
        AudioManager audioManager = mContext.getSystemService(AudioManager.class);
        boolean hasPhoneCall = usedPermGroups.contains(OPSTR_PHONE_CALL_CAMERA)
                || usedPermGroups.contains(OPSTR_PHONE_CALL_MICROPHONE);
        if (hasPhoneCall && usedPermGroups.contains(MICROPHONE) && audioManager.getMode()
                == MODE_IN_COMMUNICATION) {
            TelephonyManager telephonyManager =
                    mContext.getSystemService(TelephonyManager.class);
            List<OpUsage> permUsages = rawUsages.get(MICROPHONE);
            for (int usageNum = 0; usageNum < permUsages.size(); usageNum++) {
                if (telephonyManager.checkCarrierPrivilegesForPackage(
                        permUsages.get(usageNum).packageName)
                        == CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
                    usedPermGroups.remove(OPSTR_PHONE_CALL_CAMERA);
                    usedPermGroups.remove(OPSTR_PHONE_CALL_MICROPHONE);
                }
            }
        }

        for (int permGroupNum = 0; permGroupNum < usedPermGroups.size(); permGroupNum++) {
            boolean isPhone = false;
            String permGroup = usedPermGroups.get(permGroupNum);

            ArrayMap<OpUsage, CharSequence> usagesWithLabels =
                    getUniqueUsagesWithLabels(rawUsages.get(permGroup));

            if (permGroup.equals(OPSTR_PHONE_CALL_MICROPHONE)) {
                isPhone = true;
                permGroup = MICROPHONE;
            } else if (permGroup.equals(OPSTR_PHONE_CALL_CAMERA)) {
                isPhone = true;
                permGroup = CAMERA;
            }

            for (int usageNum = 0; usageNum < usagesWithLabels.size(); usageNum++) {
                OpUsage usage = usagesWithLabels.keyAt(usageNum);
                usages.add(new PermGroupUsage(usage.packageName, usage.uid, permGroup,
                        usage.lastAccessTime, usage.isRunning, isPhone,
                        usagesWithLabels.valueAt(usageNum)));
            }
        }

        return usages;
    }

    /**
     * Get the raw usages from the system, and then parse out the ones that are not recent enough,
     * determine which permission group each belongs in, and removes duplicates (if the same app
     * uses multiple permissions of the same group). Stores the package name, attribution tag, user,
     * running/recent info, if the usage is a phone call, per permission group.
     *
     * @param opNames a list of op names to get usage for
     *
     * @return A map of permission group -> list of usages that are recent or running
     */
    private Map<String, List<OpUsage>> getOpUsages(List<String> opNames) {
        List<AppOpsManager.PackageOps> ops;
        try {
            ops = mAppOpsManager.getPackagesForOps(opNames.toArray(new String[opNames.size()]));
        } catch (NullPointerException e) {
            // older builds might not support all the app-ops requested
            return Collections.emptyMap();
        }

        long now = System.currentTimeMillis();
        long recentThreshold = getRecentThreshold(now);
        long runningThreshold = getRunningThreshold(now);
        int opFlags = OP_FLAGS_ALL_TRUSTED;
        Map<String, Map<Integer, OpUsage>> usages = new ArrayMap<>();

        int numPkgOps = ops.size();
        for (int pkgOpNum = 0; pkgOpNum < numPkgOps; pkgOpNum++) {
            AppOpsManager.PackageOps pkgOps = ops.get(pkgOpNum);
            int uid = pkgOps.getUid();
            UserHandle user = UserHandle.getUserHandleForUid(uid);
            String packageName = pkgOps.getPackageName();

            int numOpEntries = pkgOps.getOps().size();
            for (int opEntryNum = 0; opEntryNum < numOpEntries; opEntryNum++) {
                AppOpsManager.OpEntry opEntry = pkgOps.getOps().get(opEntryNum);
                String op = opEntry.getOpStr();
                List<String> attributionTags =
                        new ArrayList<>(opEntry.getAttributedOpEntries().keySet());

                int numAttrEntries = opEntry.getAttributedOpEntries().size();
                for (int attrOpEntryNum = 0; attrOpEntryNum < numAttrEntries; attrOpEntryNum++) {
                    String attributionTag = attributionTags.get(attrOpEntryNum);
                    AppOpsManager.AttributedOpEntry attrOpEntry =
                            opEntry.getAttributedOpEntries().get(attributionTag);

                    long lastAccessTime = attrOpEntry.getLastAccessTime(opFlags);
                    if (attrOpEntry.isRunning()) {
                        lastAccessTime = now;
                    }

                    if (lastAccessTime < recentThreshold && !attrOpEntry.isRunning()) {
                        continue;
                    }

                    boolean isRunning = attrOpEntry.isRunning()
                            || lastAccessTime >= runningThreshold;

                    OpUsage proxyUsage = null;
                    AppOpsManager.OpEventProxyInfo proxy = attrOpEntry.getLastProxyInfo(opFlags);
                    if (proxy != null && proxy.getPackageName() != null) {
                        proxyUsage = new OpUsage(proxy.getPackageName(), proxy.getAttributionTag(),
                                op, proxy.getUid(), lastAccessTime, isRunning, null);
                    }

                    String permGroupName = getGroupForOp(op);
                    OpUsage usage = new OpUsage(packageName, attributionTag, op, uid,
                            lastAccessTime, isRunning, proxyUsage);

                    Integer packageAttr = usage.getPackageIdHash();
                    if (!usages.containsKey(permGroupName)) {
                        ArrayMap<Integer, OpUsage> map = new ArrayMap<>();
                        map.put(packageAttr, usage);
                        usages.put(permGroupName, map);
                    } else {
                        Map<Integer, OpUsage> permGroupUsages =
                                usages.get(permGroupName);
                        if (!permGroupUsages.containsKey(packageAttr)) {
                            permGroupUsages.put(packageAttr, usage);
                        } else if (usage.lastAccessTime
                                > permGroupUsages.get(packageAttr).lastAccessTime) {
                            permGroupUsages.put(packageAttr, usage);
                        }
                    }
                }
            }
        }

        Map<String, List<OpUsage>> flattenedUsages = new ArrayMap<>();
        List<String> permGroups = new ArrayList<>(usages.keySet());
        for (int i = 0; i < permGroups.size(); i++) {
            String permGroupName = permGroups.get(i);
            flattenedUsages.put(permGroupName, new ArrayList<>(usages.get(permGroupName).values()));
        }
        return flattenedUsages;
    }

    private CharSequence formatLabelList(List<CharSequence> labels) {
        return ListFormatter.getInstance().format(labels);
    }

    private ArrayMap<OpUsage, CharSequence> getUniqueUsagesWithLabels(List<OpUsage> usages) {
        ArrayMap<OpUsage, CharSequence> usagesAndLabels = new ArrayMap<>();

        if (usages == null || usages.isEmpty()) {
            return usagesAndLabels;
        }

        ArrayMap<Integer, OpUsage> allUsages = new ArrayMap<>();
        // map of packageName and uid hash -> most recent non-proxy-related usage for that uid.
        ArrayMap<Integer, OpUsage> mostRecentUsages = new ArrayMap<>();
        // set of all packages involved in a proxy usage
        ArraySet<Integer> proxyPackages = new ArraySet<>();
        // map of usage -> list of proxy app labels
        ArrayMap<OpUsage, ArrayList<CharSequence>> proxyLabels = new ArrayMap<>();
        // map of usage.proxy hash -> usage hash, telling us if a usage is a proxy
        ArrayMap<Integer, OpUsage> proxies = new ArrayMap<>();
        for (int i = 0; i < usages.size(); i++) {
            OpUsage usage = usages.get(i);
            allUsages.put(usage.getPackageIdHash(), usage);
            if (usage.proxy != null) {
                proxies.put(usage.proxy.getPackageIdHash(), usage);
            }
        }

        // find all possible end points for chains, and find the most recent of the rest of the uses
        for (int usageNum = 0; usageNum < usages.size(); usageNum++) {
            OpUsage usage = usages.get(usageNum);
            if (usage == null) {
                continue;
            }

            int usageAttr = usage.getPackageIdHash();
            // If this usage has a proxy, but is not a proxy, it is the end of a chain.
            // TODO remove once camera converted
            if (!proxies.containsKey(usageAttr) && usage.proxy != null
                    && !usage.op.equals(OPSTR_RECORD_AUDIO)) {
                proxyLabels.put(usage, new ArrayList<>());
                proxyPackages.add(usage.getPackageIdHash());
            }
            // If this usage is not by the system, and is more recent than the next-most recent
            // for it's uid and package name, save it.
            int usageId = usage.getPackageIdHash();
            OpUsage lastMostRecent = mostRecentUsages.get(usageId);
            if (shouldShowPackage(usage.packageName) && (lastMostRecent == null
                    || usage.lastAccessTime > lastMostRecent.lastAccessTime)) {
                mostRecentUsages.put(usageId, usage);
            }
        }

        // get all the proxy labels
        for (int numStart = 0; numStart < proxyLabels.size(); numStart++) {
            OpUsage start = proxyLabels.keyAt(numStart);
            // Remove any non-proxy usage for the starting package
            mostRecentUsages.remove(start.getPackageIdHash());
            OpUsage currentUsage = proxyLabels.keyAt(numStart);
            ArrayList<CharSequence> proxyLabelList = proxyLabels.get(currentUsage);
            if (currentUsage == null || proxyLabelList == null) {
                continue;
            }
            int iterNum = 0;
            int maxUsages = allUsages.size();
            while (currentUsage.proxy != null) {

                if (allUsages.containsKey(currentUsage.proxy.getPackageIdHash())) {
                    currentUsage = allUsages.get(currentUsage.proxy.getPackageIdHash());
                } else {
                    // We are missing the proxy usage. This may be because it's a one-step trusted
                    // proxy. Check if we should show the proxy label, and show it, if so.
                    OpUsage proxy = currentUsage.proxy;
                    if (shouldShowPackage(proxy.packageName)) {
                        currentUsage = proxy;
                        // We've effectively added one usage, so increment the max number of usages
                        maxUsages++;
                    } else {
                        break;
                    }
                }

                if (currentUsage == null || iterNum == maxUsages
                        || currentUsage.getPackageIdHash() == start.getPackageIdHash()) {
                    // We have an invalid state, or a cycle, so break
                    break;
                }

                proxyPackages.add(currentUsage.getPackageIdHash());
                // Don't add an app label for the main app, or the system app
                if (!currentUsage.packageName.equals(start.packageName)
                        && shouldShowPackage(currentUsage.packageName)) {
                    try {
                        PackageManager userPkgManager =
                                getUserContext(currentUsage.getUser()).getPackageManager();
                        ApplicationInfo appInfo = userPkgManager.getApplicationInfo(
                                currentUsage.packageName, 0);
                        CharSequence appLabel = appInfo.loadLabel(userPkgManager);
                        // If we don't already have the app label add it
                        if (!proxyLabelList.contains(appLabel)) {
                            proxyLabelList.add(appLabel);
                        }
                    } catch (PackageManager.NameNotFoundException e) {
                        // Ignore
                    }
                }
                iterNum++;
            }

            // TODO ntmyren: remove this proxy logic once camera is converted to AttributionSource
            // For now: don't add mic proxy usages
            if (!start.op.equals(OPSTR_RECORD_AUDIO)) {
                usagesAndLabels.put(start,
                        proxyLabelList.isEmpty() ? null : formatLabelList(proxyLabelList));
            }
        }

        for (int i = 0; i < mAttributionChains.size(); i++) {
            List<AccessChainLink> usageList = mAttributionChains.valueAt(i);
            int lastVisible = usageList.size() - 1;
            // TODO ntmyren: remove this mic code once camera is converted to AttributionSource
            // if the list is empty or incomplete, do not show it.
            if (usageList.isEmpty() || !usageList.get(lastVisible).isEnd()
                    || !usageList.get(0).isStart()
                    || !usageList.get(lastVisible).usage.op.equals(OPSTR_RECORD_AUDIO)) {
                continue;
            }

            //TODO ntmyren: remove once camera etc. etc.
            for (AccessChainLink link: usageList) {
                proxyPackages.add(link.usage.getPackageIdHash());
            }

            AccessChainLink start = usageList.get(0);
            AccessChainLink lastVisibleLink = usageList.get(lastVisible);
            while (lastVisible > 0 && !shouldShowPackage(lastVisibleLink.usage.packageName)) {
                lastVisible--;
                lastVisibleLink = usageList.get(lastVisible);
            }
            String proxyLabel = null;
            if (!lastVisibleLink.usage.packageName.equals(start.usage.packageName)) {
                try {
                    PackageManager userPkgManager =
                            getUserContext(lastVisibleLink.usage.getUser()).getPackageManager();
                    ApplicationInfo appInfo = userPkgManager.getApplicationInfo(
                            lastVisibleLink.usage.packageName, 0);
                    proxyLabel = appInfo.loadLabel(userPkgManager).toString();
                } catch (PackageManager.NameNotFoundException e) {
                    // do nothing
                }

            }
            usagesAndLabels.put(start.usage, proxyLabel);
        }

        for (int packageHash : mostRecentUsages.keySet()) {
            if (!proxyPackages.contains(packageHash)) {
                usagesAndLabels.put(mostRecentUsages.get(packageHash), null);
            }
        }

        return usagesAndLabels;
    }

    private boolean shouldShowPackage(String packageName) {
        return PermissionManager.shouldShowPackageForIndicatorCached(mContext, packageName);
    }

    /**
     * Represents the usage of an App op by a particular package and attribution
     */
    private static class OpUsage {

        public final String packageName;
        public final String attributionTag;
        public final String op;
        public final int uid;
        public final long lastAccessTime;
        public final OpUsage proxy;
        public final boolean isRunning;

        OpUsage(String packageName, String attributionTag, String op, int uid, long lastAccessTime,
                boolean isRunning, OpUsage proxy) {
            this.packageName = packageName;
            this.attributionTag = attributionTag;
            this.op = op;
            this.uid = uid;
            this.lastAccessTime = lastAccessTime;
            this.isRunning = isRunning;
            this.proxy = proxy;
        }

        public UserHandle getUser() {
            return UserHandle.getUserHandleForUid(uid);
        }

        public int getPackageIdHash() {
            return Objects.hash(packageName, uid);
        }

        @Override
        public int hashCode() {
            return Objects.hash(packageName, attributionTag, op, uid, lastAccessTime, isRunning);
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof OpUsage)) {
                return false;
            }
            OpUsage other = (OpUsage) obj;
            return Objects.equals(packageName, other.packageName) && Objects.equals(attributionTag,
                    other.attributionTag) && Objects.equals(op, other.op) && uid == other.uid
                    && lastAccessTime == other.lastAccessTime && isRunning == other.isRunning;
        }
    }

    private static class AccessChainLink {
        public final OpUsage usage;
        public final @AttributionFlags int flags;

        AccessChainLink(String op, String packageName, String attributionTag, int uid,
                int flags) {
            this.usage = new OpUsage(packageName, attributionTag, op, uid,
                    System.currentTimeMillis(), true, null);
            this.flags = flags;
        }

        public boolean isEnd() {
            return (flags & ATTRIBUTION_FLAG_ACCESSOR) != 0;
        }

        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;
        }
    }
}
