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

Commit 38e2d687 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adds client info in ContextHubService dump"

parents c7f313f3 672d8a7a
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -29,10 +29,12 @@ import android.hardware.location.ContextHubTransaction;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.NanoAppMessage;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;

/**
@@ -96,6 +98,16 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     */
    private final PendingIntentRequest mPendingIntentRequest;

    /*
     * The host package associated with this client.
     */
    private final String mPackage;

    /*
     * True if a PendingIntent has been cancelled.
     */
    private AtomicBoolean mIsPendingIntentCancelled = new AtomicBoolean(false);

    /*
     * Helper class to manage registered PendingIntent requests from the client.
     */
@@ -110,11 +122,14 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
         */
        private long mNanoAppId;

        private boolean mValid = false;

        PendingIntentRequest() {}

        PendingIntentRequest(PendingIntent pendingIntent, long nanoAppId) {
            mPendingIntent = pendingIntent;
            mNanoAppId = nanoAppId;
            mValid = true;
        }

        public long getNanoAppId() {
@@ -132,6 +147,10 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
        public void clear() {
            mPendingIntent = null;
        }

        public boolean isValid() {
            return mValid;
        }
    }

    /* package */ ContextHubClientBroker(
@@ -145,6 +164,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
        mHostEndPointId = hostEndPointId;
        mCallbackInterface = callback;
        mPendingIntentRequest = new PendingIntentRequest();
        mPackage = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
    }

    /* package */ ContextHubClientBroker(
@@ -157,6 +177,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
        mAttachedContextHubInfo = contextHubInfo;
        mHostEndPointId = hostEndPointId;
        mPendingIntentRequest = new PendingIntentRequest(pendingIntent, nanoAppId);
        mPackage = pendingIntent.getCreatorPackage();
    }

    /**
@@ -312,6 +333,13 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
        }
    }

    /**
     * @return true if the client is a PendingIntent client that has been cancelled.
     */
    /* package */ boolean isPendingIntentCancelled() {
        return mIsPendingIntentCancelled.get();
    }

    /**
     * Helper function to invoke a specified client callback, if the connection is open.
     *
@@ -392,6 +420,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
                    Manifest.permission.LOCATION_HARDWARE /* requiredPermission */,
                    null /* options */);
        } catch (PendingIntent.CanceledException e) {
            mIsPendingIntentCancelled.set(true);
            // The PendingIntent is no longer valid
            Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
                    + " (host endpoint ID " + mHostEndPointId + ")");
@@ -419,4 +448,20 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
            mRegistered = false;
        }
    }

    @Override
    public String toString() {
        String out = "[ContextHubClient ";
        out += "endpointID: " + getHostEndPointId() + ", ";
        out += "contextHub: " + getAttachedContextHubId() + ", ";
        if (mPendingIntentRequest.isValid()) {
            out += "intentCreatorPackage: " + mPackage + ", ";
            out += "nanoAppId: 0x" + Long.toHexString(mPendingIntentRequest.getNanoAppId());
        } else {
            out += "package: " + mPackage;
        }
        out += "]";

        return out;
    }
}
+106 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.location;

import android.annotation.IntDef;
import android.app.PendingIntent;
import android.content.Context;
import android.hardware.contexthub.V1_0.ContextHubMsg;
@@ -27,7 +28,12 @@ import android.hardware.location.NanoAppMessage;
import android.os.RemoteException;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Consumer;

/**
@@ -71,6 +77,79 @@ import java.util.function.Consumer;
     */
    private int mNextHostEndPointId = 0;

    /*
     * The list of previous registration records.
     */
    private static final int NUM_CLIENT_RECORDS = 20;
    private final ConcurrentLinkedEvictingDeque<RegistrationRecord> mRegistrationRecordDeque =
            new ConcurrentLinkedEvictingDeque<>(NUM_CLIENT_RECORDS);

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "ACTION_" }, value = {
            ACTION_REGISTERED,
            ACTION_UNREGISTERED,
            ACTION_CANCELLED,
    })
    public @interface Action {}
    public static final int ACTION_REGISTERED = 0;
    public static final int ACTION_UNREGISTERED = 1;
    public static final int ACTION_CANCELLED = 2;

    /**
     * Helper class to make a ConcurrentLinkedDeque fixed-size, evicting old entries when full.
     */
    private class ConcurrentLinkedEvictingDeque<E> extends ConcurrentLinkedDeque<E> {
        private int mSize;

        ConcurrentLinkedEvictingDeque(int size) {
            mSize = size;
        }

        @Override
        public boolean add(E elem) {
            synchronized (this) {
                if (size() == mSize) {
                    poll();
                }

                return super.add(elem);
            }
        }
    }

    /**
     * A container class to store a record of ContextHubClient registration.
     */
    private class RegistrationRecord {
        private final String mBroker;
        private final int mAction;
        private final String mDate;

        RegistrationRecord(String broker, @Action int action) {
            mBroker = broker;
            mAction = action;
            Calendar instance = Calendar.getInstance();
            mDate = String.format("%02d", instance.get(Calendar.MONTH) + 1) // Jan == 0
                + "/" + String.format("%02d", instance.get(Calendar.DAY_OF_MONTH))
                + " " + String.format("%02d", instance.get(Calendar.HOUR_OF_DAY))
                + ":" + String.format("%02d", instance.get(Calendar.MINUTE))
                + ":" + String.format("%02d", instance.get(Calendar.SECOND))
                + "." + String.format("%03d", instance.get(Calendar.MILLISECOND));
        }

        @Override
        public String toString() {
            String out = "";
            out += mDate + " ";
            out += mAction == ACTION_REGISTERED ? "+ " : "- ";
            out += mBroker;
            if (mAction == ACTION_CANCELLED) {
                out += " (cancelled)";
            }
            return out;
        }
    }

    /* package */ ContextHubClientManager(
            Context context, IContexthub contextHubProxy) {
        mContext = context;
@@ -96,6 +175,8 @@ import java.util.function.Consumer;
                    mContext, mContextHubProxy, this /* clientManager */, contextHubInfo,
                    hostEndPointId, clientCallback);
            mHostEndPointIdToClientMap.put(hostEndPointId, broker);
            mRegistrationRecordDeque.add(
                    new RegistrationRecord(broker.toString(), ACTION_REGISTERED));
        }

        try {
@@ -136,6 +217,8 @@ import java.util.function.Consumer;
                        hostEndPointId, pendingIntent, nanoAppId);
                mHostEndPointIdToClientMap.put(hostEndPointId, broker);
                registerString = "Registered";
                mRegistrationRecordDeque.add(
                        new RegistrationRecord(broker.toString(), ACTION_REGISTERED));
            }
        }

@@ -178,6 +261,13 @@ import java.util.function.Consumer;
     * @param hostEndPointId the host endpoint ID of the client that has died
     */
    /* package */ void unregisterClient(short hostEndPointId) {
        ContextHubClientBroker broker = mHostEndPointIdToClientMap.get(hostEndPointId);
        if (broker != null) {
            @Action int action =
                    broker.isPendingIntentCancelled() ? ACTION_CANCELLED : ACTION_UNREGISTERED;
            mRegistrationRecordDeque.add(new RegistrationRecord(broker.toString(), action));
        }

        if (mHostEndPointIdToClientMap.remove(hostEndPointId) != null) {
            Log.d(TAG, "Unregistered client with host endpoint ID " + hostEndPointId);
        } else {
@@ -285,4 +375,20 @@ import java.util.function.Consumer;

        return null;
    }

    @Override
    public String toString() {
        String out = "";
        for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
            out += broker + "\n";
        }

        out += "\nRegistration history:\n";
        Iterator<RegistrationRecord> it = mRegistrationRecordDeque.descendingIterator();
        while (it.hasNext()) {
            out += it.next() + "\n";
        }

        return out;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -795,6 +795,10 @@ public class ContextHubService extends IContextHubService.Stub {
        // Dump nanoAppHash
        mNanoAppStateManager.foreachNanoAppInstanceInfo((info) -> pw.println(info));

        pw.println("");
        pw.println("=================== CLIENTS ====================");
        pw.println(mClientManager);

        // dump eventLog
    }