/*
 * Copyright (C) 2008 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.
 */

#pragma once

#include <atomic>
#include <stdint.h>
#include <binder/IBinder.h>

// ---------------------------------------------------------------------------
namespace android {

namespace internal {
class Stability;
}

class BBinder : public IBinder
{
public:
                        BBinder();

    virtual const String16& getInterfaceDescriptor() const;
    virtual bool        isBinderAlive() const;
    virtual status_t    pingBinder();
    virtual status_t    dump(int fd, const Vector<String16>& args);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0) final;

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
                                    void* cookie = nullptr,
                                    uint32_t flags = 0);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    unlinkToDeath(  const wp<DeathRecipient>& recipient,
                                        void* cookie = nullptr,
                                        uint32_t flags = 0,
                                        wp<DeathRecipient>* outRecipient = nullptr);

    virtual void        attachObject(   const void* objectID,
                                        void* object,
                                        void* cleanupCookie,
                                        object_cleanup_func func) final;
    virtual void*       findObject(const void* objectID) const final;
    virtual void        detachObject(const void* objectID) final;

    virtual BBinder*    localBinder();

    bool                isRequestingSid();
    // This must be called before the object is sent to another process. Not thread safe.
    void                setRequestingSid(bool requestSid);

    sp<IBinder>         getExtension();
    // This must be called before the object is sent to another process. Not thread safe.
    void                setExtension(const sp<IBinder>& extension);

    // This must be called before the object is sent to another process. Not thread safe.
    //
    // This function will abort if improper parameters are set. This is like
    // sched_setscheduler. However, it sets the minimum scheduling policy
    // only for the duration that this specific binder object is handling the
    // call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In
    // this case, the scheduling priority will not actually be modified from
    // binder defaults. See also IPCThreadState::disableBackgroundScheduling.
    //
    // Appropriate values are:
    // SCHED_NORMAL: -20 <= priority <= 19
    // SCHED_RR/SCHED_FIFO: 1 <= priority <= 99
    void                setMinSchedulerPolicy(int policy, int priority);
    int                 getMinSchedulerPolicy();
    int                 getMinSchedulerPriority();

    // Whether realtime scheduling policies are inherited.
    bool                isInheritRt();
    // This must be called before the object is sent to another process. Not thread safe.
    void                setInheritRt(bool inheritRt);

    pid_t               getDebugPid();

    // Whether this binder has been sent to another process.
    bool wasParceled();
    // Consider this binder as parceled (setup/init-related calls should no
    // longer by called. This is automatically set by when this binder is sent
    // to another process.
    void setParceled();

    [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd,
                                             const sp<IBinder>& keepAliveBinder);

protected:
    virtual             ~BBinder();

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

private:
                        BBinder(const BBinder& o);
            BBinder&    operator=(const BBinder& o);

    class RpcServerLink;
    class Extras;

    Extras*             getOrCreateExtras();

    [[nodiscard]] status_t setRpcClientDebug(const Parcel& data);
    void removeRpcServerLink(const sp<RpcServerLink>& link);

    std::atomic<Extras*> mExtras;

    friend ::android::internal::Stability;
    int16_t mStability;
    bool mParceled;
    uint8_t mReserved0;

#ifdef __LP64__
    int32_t mReserved1;
#endif
};

// ---------------------------------------------------------------------------

class BpRefBase : public virtual RefBase
{
protected:
    explicit                BpRefBase(const sp<IBinder>& o);
    virtual                 ~BpRefBase();
    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);

    inline IBinder* remote() const { return mRemote; }
    inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); }

private:
                            BpRefBase(const BpRefBase& o);
    BpRefBase&              operator=(const BpRefBase& o);

    IBinder* const          mRemote;
    RefBase::weakref_type*  mRefs;
    std::atomic<int32_t>    mState;
};

} // namespace android

// ---------------------------------------------------------------------------
