Merge "Add force downgrade to vendor stability test"
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 9de344a..3ebdeee 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -14,6 +14,7 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
 
     srcs: [
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 0dbab4e..2f55249 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -239,7 +239,8 @@
 #endif  // !VENDORSERVICEMANAGER
 
     // implicitly unlinked when the binder is removed
-    if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
+    if (binder->remoteBinder() != nullptr &&
+        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
         LOG(ERROR) << "Could not linkToDeath when adding " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -307,7 +308,9 @@
         return Status::fromExceptionCode(Status::EX_NULL_POINTER);
     }
 
-    if (OK != IInterface::asBinder(callback)->linkToDeath(this)) {
+    if (OK !=
+        IInterface::asBinder(callback)->linkToDeath(
+                sp<ServiceManager>::fromExisting(this))) {
         LOG(ERROR) << "Could not linkToDeath when adding " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -461,7 +464,8 @@
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
     }
 
-    if (OK != IInterface::asBinder(cb)->linkToDeath(this)) {
+    if (OK !=
+        IInterface::asBinder(cb)->linkToDeath(sp<ServiceManager>::fromExisting(this))) {
         LOG(ERROR) << "Could not linkToDeath when adding client callback for " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -491,7 +495,7 @@
 }
 
 ssize_t ServiceManager::Service::getNodeStrongRefCount() {
-    sp<BpBinder> bpBinder = binder->remoteBinder();
+    sp<BpBinder> bpBinder = sp<BpBinder>::fromExisting(binder->remoteBinder());
     if (bpBinder == nullptr) return -1;
 
     return ProcessState::self()->getStrongRefCountForNode(bpBinder);
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index 627dfe6..8c1beac 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -39,7 +39,7 @@
 class BinderCallback : public LooperCallback {
 public:
     static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
-        sp<BinderCallback> cb = new BinderCallback;
+        sp<BinderCallback> cb = sp<BinderCallback>::make();
 
         int binder_fd = -1;
         IPCThreadState::self()->setupPolling(&binder_fd);
@@ -65,7 +65,7 @@
 class ClientCallbackCallback : public LooperCallback {
 public:
     static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper, const sp<ServiceManager>& manager) {
-        sp<ClientCallbackCallback> cb = new ClientCallbackCallback(manager);
+        sp<ClientCallbackCallback> cb = sp<ClientCallbackCallback>::make(manager);
 
         int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0 /*flags*/);
         LOG_ALWAYS_FATAL_IF(fdTimer < 0, "Failed to timerfd_create: fd: %d err: %d", fdTimer, errno);
@@ -105,6 +105,7 @@
         return 1;  // Continue receiving callbacks.
     }
 private:
+    friend sp<ClientCallbackCallback>;
     ClientCallbackCallback(const sp<ServiceManager>& manager) : mManager(manager) {}
     sp<ServiceManager> mManager;
 };
@@ -120,7 +121,7 @@
     ps->setThreadPoolMaxThreadCount(0);
     ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
 
-    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
+    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
     if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
         LOG(ERROR) << "Could not self register servicemanager";
     }
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index fb9f9df..5d5a75e 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -46,7 +46,7 @@
         }
     };
 
-    return new LinkableBinder;
+    return sp<LinkableBinder>::make();
 }
 
 class MockAccess : public Access {
@@ -71,7 +71,7 @@
     ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true));
     ON_CALL(*access, canList(_)).WillByDefault(Return(true));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
     return sm;
 }
 
@@ -119,7 +119,7 @@
             .uid = uid,
         }));
         EXPECT_CALL(*access, canAdd(_, _)).Times(0);
-        sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+        sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
         EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
             IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -161,7 +161,7 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -194,7 +194,7 @@
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
     EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -218,7 +218,7 @@
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
     EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     sp<IBinder> service = getBinder();
     EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
@@ -244,7 +244,7 @@
     // TODO(b/136023468): when security check is first, this should be called first
     // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -261,7 +261,7 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     std::vector<std::string> out;
     EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
@@ -329,9 +329,9 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = sp<ServiceManager>::make(std::move(access));
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_EQ(sm->registerForNotifications("foofoo", cb).exceptionCode(),
         Status::EX_SECURITY);
@@ -343,9 +343,9 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = sp<ServiceManager>::make(std::move(access));
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     // should always hit security error first
     EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
@@ -355,7 +355,7 @@
 TEST(ServiceNotifications, InvalidName) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_EQ(sm->registerForNotifications("foo@foo", cb).exceptionCode(),
         Status::EX_ILLEGAL_ARGUMENT);
@@ -371,7 +371,7 @@
 TEST(ServiceNotifications, Unregister) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
     EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(), 0);
@@ -380,7 +380,7 @@
 TEST(ServiceNotifications, UnregisterWhenNoRegistrationExists) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
         Status::EX_ILLEGAL_STATE);
@@ -389,7 +389,7 @@
 TEST(ServiceNotifications, NoNotification) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
     EXPECT_TRUE(sm->addService("otherservice", getBinder(),
@@ -402,7 +402,7 @@
 TEST(ServiceNotifications, GetNotification) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     sp<IBinder> service = getBinder();
 
@@ -417,7 +417,7 @@
 TEST(ServiceNotifications, GetNotificationForAlreadyRegisteredService) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     sp<IBinder> service = getBinder();
 
@@ -433,7 +433,7 @@
 TEST(ServiceNotifications, GetMultipleNotification) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     sp<IBinder> binder1 = getBinder();
     sp<IBinder> binder2 = getBinder();
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index f28af96..2715d6a 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -69,7 +69,6 @@
     "IUidObserver.cpp",
     "PermissionCache.cpp",
     "PermissionController.cpp",
-    "IpPrefix.cpp",
     ":activity_manager_procstate_aidl",
 ]
 
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
deleted file mode 100644
index 4edc493..0000000
--- a/libs/binder/IpPrefix.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#define LOG_TAG "IpPrefix"
-
-#include <binder/IpPrefix.h>
-#include <vector>
-
-#include <binder/IBinder.h>
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-
-using android::BAD_VALUE;
-using android::NO_ERROR;
-using android::Parcel;
-using android::status_t;
-
-namespace android {
-
-namespace net {
-
-#define RETURN_IF_FAILED(calledOnce)                                     \
-    {                                                                    \
-        status_t returnStatus = calledOnce;                              \
-        if (returnStatus) {                                              \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return returnStatus;                                         \
-         }                                                               \
-    }
-
-status_t IpPrefix::writeToParcel(Parcel* parcel) const {
-    /*
-     * Keep implementation in sync with writeToParcel() in
-     * frameworks/base/core/java/android/net/IpPrefix.java.
-     */
-    std::vector<uint8_t> byte_vector;
-
-    if (mIsIpv6) {
-        const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mIn6Addr);
-        byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
-    } else {
-        const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mInAddr);
-        byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
-    }
-
-    RETURN_IF_FAILED(parcel->writeByteVector(byte_vector));
-    RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(mPrefixLength)));
-
-    return NO_ERROR;
-}
-
-status_t IpPrefix::readFromParcel(const Parcel* parcel) {
-    /*
-     * Keep implementation in sync with readFromParcel() in
-     * frameworks/base/core/java/android/net/IpPrefix.java.
-     */
-    std::vector<uint8_t> byte_vector;
-
-    RETURN_IF_FAILED(parcel->readByteVector(&byte_vector));
-    RETURN_IF_FAILED(parcel->readInt32(&mPrefixLength));
-
-    if (byte_vector.size() == 16) {
-        mIsIpv6 = true;
-        memcpy((void*)&mUnion.mIn6Addr, &byte_vector[0], sizeof(mUnion.mIn6Addr));
-
-    } else if (byte_vector.size() == 4) {
-        mIsIpv6 = false;
-        memcpy((void*)&mUnion.mInAddr, &byte_vector[0], sizeof(mUnion.mInAddr));
-
-    } else {
-        ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-        return BAD_VALUE;
-    }
-
-    return NO_ERROR;
-}
-
-const struct in6_addr& IpPrefix::getAddressAsIn6Addr() const
-{
-    return mUnion.mIn6Addr;
-}
-
-const struct in_addr& IpPrefix::getAddressAsInAddr() const
-{
-    return mUnion.mInAddr;
-}
-
-bool IpPrefix::getAddressAsIn6Addr(struct in6_addr* addr) const
-{
-    if (isIpv6()) {
-        *addr = mUnion.mIn6Addr;
-        return true;
-    }
-    return false;
-}
-
-bool IpPrefix::getAddressAsInAddr(struct in_addr* addr) const
-{
-    if (isIpv4()) {
-        *addr = mUnion.mInAddr;
-        return true;
-    }
-    return false;
-}
-
-bool IpPrefix::isIpv6() const
-{
-    return mIsIpv6;
-}
-
-bool IpPrefix::isIpv4() const
-{
-    return !mIsIpv6;
-}
-
-int32_t IpPrefix::getPrefixLength() const
-{
-    return mPrefixLength;
-}
-
-void IpPrefix::setAddress(const struct in6_addr& addr)
-{
-    mUnion.mIn6Addr = addr;
-    mIsIpv6 = true;
-}
-
-void IpPrefix::setAddress(const struct in_addr& addr)
-{
-    mUnion.mInAddr = addr;
-    mIsIpv6 = false;
-}
-
-void IpPrefix::setPrefixLength(int32_t prefix)
-{
-    mPrefixLength = prefix;
-}
-
-bool operator==(const IpPrefix& lhs, const IpPrefix& rhs)
-{
-    if (lhs.mIsIpv6 != rhs.mIsIpv6) {
-        return false;
-    }
-
-    if (lhs.mPrefixLength != rhs.mPrefixLength) {
-        return false;
-    }
-
-    if (lhs.mIsIpv6) {
-        return 0 == memcmp(lhs.mUnion.mIn6Addr.s6_addr, rhs.mUnion.mIn6Addr.s6_addr, sizeof(struct in6_addr));
-    }
-
-    return 0 == memcmp(&lhs.mUnion.mInAddr, &rhs.mUnion.mInAddr, sizeof(struct in_addr));
-}
-
-}  // namespace net
-
-}  // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 34a474b..3f0b0df 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -555,12 +555,17 @@
 }
 
 void Parcel::markForBinder(const sp<IBinder>& binder) {
+    LOG_ALWAYS_FATAL_IF(mData != nullptr, "format must be set before data is written");
+
     if (binder && binder->remoteBinder() && binder->remoteBinder()->isRpcBinder()) {
         markForRpc(binder->remoteBinder()->getPrivateAccessorForId().rpcConnection());
     }
 }
 
 void Parcel::markForRpc(const sp<RpcConnection>& connection) {
+    LOG_ALWAYS_FATAL_IF(mData != nullptr && mOwner == nullptr,
+                        "format must be set before data is written OR on IPC data");
+
     LOG_ALWAYS_FATAL_IF(connection == nullptr, "markForRpc requires connection");
     mConnection = connection;
 }
@@ -2100,6 +2105,9 @@
 void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
     const binder_size_t* objects, size_t objectsCount, release_func relFunc)
 {
+    // this code uses 'mOwner == nullptr' to understand whether it owns memory
+    LOG_ALWAYS_FATAL_IF(relFunc == nullptr, "must provide cleanup function");
+
     freeData();
 
     mData = const_cast<uint8_t*>(data);
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 3b3adca..755ff35 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -312,8 +312,8 @@
     return waitForReply(fd, connection, reply);
 }
 
-static void cleanup_data(Parcel* p, const uint8_t* data, size_t dataSize,
-                         const binder_size_t* objects, size_t objectsCount) {
+static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize,
+                               const binder_size_t* objects, size_t objectsCount) {
     (void)p;
     delete[] const_cast<uint8_t*>(data - offsetof(RpcWireReply, data));
     (void)dataSize;
@@ -351,7 +351,7 @@
     if (rpcReply->status != OK) return rpcReply->status;
 
     reply->ipcSetDataReference(rpcReply->data, command.bodySize - offsetof(RpcWireReply, data),
-                               nullptr, 0, cleanup_data);
+                               nullptr, 0, cleanup_reply_data);
 
     reply->markForRpc(connection);
 
@@ -427,6 +427,15 @@
     return processTransactInternal(fd, connection, std::move(transactionData));
 }
 
+static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t dataSize,
+                                        const binder_size_t* objects, size_t objectsCount) {
+    (void)p;
+    (void)data;
+    (void)dataSize;
+    (void)objects;
+    (void)objectsCount;
+}
+
 status_t RpcState::processTransactInternal(const base::unique_fd& fd,
                                            const sp<RpcConnection>& connection,
                                            std::vector<uint8_t>&& transactionData) {
@@ -490,7 +499,12 @@
     }
 
     Parcel data;
-    data.setData(transaction->data, transactionData.size() - offsetof(RpcWireTransaction, data));
+    // transaction->data is owned by this function. Parcel borrows this data and
+    // only holds onto it for the duration of this function call. Parcel will be
+    // deleted before the 'transactionData' object.
+    data.ipcSetDataReference(transaction->data,
+                             transactionData.size() - offsetof(RpcWireTransaction, data),
+                             nullptr /*object*/, 0 /*objectCount*/, do_nothing_to_transact_data);
     data.markForRpc(connection);
 
     Parcel reply;
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index f4a21dd..ea91753 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -186,7 +186,7 @@
 inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
         const String16& _descriptor)
 {
-    if (_descriptor == INTERFACE::descriptor) return this;
+    if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
     return nullptr;
 }
 
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
deleted file mode 100644
index a8faa3f..0000000
--- a/libs/binder/include/binder/IpPrefix.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2015 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
-
-#ifndef __ANDROID_VNDK__
-
-#include <netinet/in.h>
-
-#include <binder/Parcelable.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace net {
-
-/*
- * C++ implementation of the Java class android.net.IpPrefix
- */
-class IpPrefix : public Parcelable {
-public:
-    IpPrefix() = default;
-    virtual ~IpPrefix() = default;
-    IpPrefix(const IpPrefix& prefix) = default;
-
-    IpPrefix(const struct in6_addr& addr, int32_t plen):
-        mUnion(addr), mPrefixLength(plen), mIsIpv6(true) { }
-
-    IpPrefix(const struct in_addr& addr, int32_t plen):
-        mUnion(addr), mPrefixLength(plen), mIsIpv6(false) { }
-
-    bool getAddressAsIn6Addr(struct in6_addr* addr) const;
-    bool getAddressAsInAddr(struct in_addr* addr) const;
-
-    const struct in6_addr& getAddressAsIn6Addr() const;
-    const struct in_addr& getAddressAsInAddr() const;
-
-    bool isIpv6() const;
-    bool isIpv4() const;
-
-    int32_t getPrefixLength() const;
-
-    void setAddress(const struct in6_addr& addr);
-    void setAddress(const struct in_addr& addr);
-
-    void setPrefixLength(int32_t prefix);
-
-    friend bool operator==(const IpPrefix& lhs, const IpPrefix& rhs);
-
-    friend bool operator!=(const IpPrefix& lhs, const IpPrefix& rhs) {
-        return !(lhs == rhs);
-    }
-
-public:
-    // Overrides
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
-private:
-    union InternalUnion {
-        InternalUnion() = default;
-        explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { }
-        explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { }
-        struct in6_addr mIn6Addr;
-        struct in_addr mInAddr;
-    } mUnion;
-    int32_t mPrefixLength;
-    bool mIsIpv6;
-};
-
-}  // namespace net
-
-}  // namespace android
-
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 9578372..211790d 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -101,10 +101,6 @@
     // is for an RPC transaction).
     void markForBinder(const sp<IBinder>& binder);
 
-    // Whenever possible, markForBinder should be preferred. This method is
-    // called automatically on reply Parcels for RPC transactions.
-    void markForRpc(const sp<RpcConnection>& connection);
-
     // Whether this Parcel is written for RPC transactions (after calls to
     // markForBinder or markForRpc).
     bool isForRpc() const;
@@ -540,6 +536,10 @@
                                             const binder_size_t* objects, size_t objectsCount,
                                             release_func relFunc);
 
+    // Whenever possible, markForBinder should be preferred. This method is
+    // called automatically on reply Parcels for RPC transactions.
+    void markForRpc(const sp<RpcConnection>& connection);
+
     status_t            finishWrite(size_t len);
     void                releaseObjects();
     void                acquireObjects();
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
index a300575..efa922d 100644
--- a/libs/binder/include/binder/RpcConnection.h
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -106,6 +106,7 @@
     };
 
 private:
+    friend sp<RpcConnection>;
     RpcConnection();
 
     bool addServer(const SocketAddress& address);
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 0f59de4..76afd4c 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -598,6 +598,8 @@
     }
 
     *in = new AParcel(binder);
+    (*in)->get()->markForBinder(binder->getBinder());
+
     status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
     binder_status_t ret = PruneStatusT(status);
 
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index aebc7f4..b4f6358 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -29,11 +29,7 @@
 
     explicit AParcel(AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
     AParcel(AIBinder* binder, ::android::Parcel* parcel, bool owns)
-        : mBinder(binder), mParcel(parcel), mOwns(owns) {
-        if (binder != nullptr) {
-            parcel->markForBinder(binder->getBinder());
-        }
-    }
+        : mBinder(binder), mParcel(parcel), mOwns(owns) {}
 
     ~AParcel() {
         if (mOwns) {
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 5f68a25..985d086 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -44,6 +44,13 @@
 
 namespace android {
 
+TEST(BinderRpcParcel, EntireParcelFormatted) {
+    Parcel p;
+    p.writeInt32(3);
+
+    EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "");
+}
+
 using android::binder::Status;
 
 #define EXPECT_OK(status)                 \
diff --git a/services/memtrackproxy/Android.bp b/services/memtrackproxy/Android.bp
new file mode 100644
index 0000000..ee8b247
--- /dev/null
+++ b/services/memtrackproxy/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 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.
+
+cc_library_shared {
+    name: "libmemtrackproxy",
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libbinder",
+        "libhidlbase",
+        "liblog",
+        "libcutils",
+        "libutils",
+        "android.hardware.memtrack@1.0",
+        "android.hardware.memtrack-V1-ndk_platform",
+    ],
+    srcs: [
+        "MemtrackProxy.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    local_include_dirs: [
+        "include/memtrackproxy",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.memtrack@1.0",
+        "android.hardware.memtrack-V1-ndk_platform",
+    ],
+}
diff --git a/services/memtrackproxy/MemtrackProxy.cpp b/services/memtrackproxy/MemtrackProxy.cpp
new file mode 100644
index 0000000..8da6e89
--- /dev/null
+++ b/services/memtrackproxy/MemtrackProxy.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "MemtrackProxy.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <private/android_filesystem_config.h>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+// Check Memtrack Flags
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SMAPS_ACCOUNTED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SMAPS_ACCOUNTED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SMAPS_UNACCOUNTED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SMAPS_UNACCOUNTED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SHARED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SHARED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SHARED_PSS) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SHARED_PSS));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::PRIVATE) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_PRIVATE));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SYSTEM) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SYSTEM));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::DEDICATED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_DEDICATED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::NONSECURE) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_NONSECURE));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SECURE) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SECURE));
+
+// Check Memtrack Types
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::OTHER) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::OTHER));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::GL) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::GL));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::GRAPHICS) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::GRAPHICS));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::MULTIMEDIA) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::MULTIMEDIA));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::CAMERA) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::CAMERA));
+
+__attribute__((warn_unused_result)) bool translate(const V1_0_hidl::MemtrackRecord& in,
+                                                   V1_aidl::MemtrackRecord* out) {
+    // Convert uint64_t to int64_t (long in AIDL). AIDL doesn't support unsigned types.
+    if (in.sizeInBytes > std::numeric_limits<int64_t>::max() || in.sizeInBytes < 0) {
+        return false;
+    }
+    out->sizeInBytes = static_cast<int64_t>(in.sizeInBytes);
+
+    // It's ok to just assign directly, since this is a bitmap.
+    out->flags = in.flags;
+    return true;
+}
+
+sp<V1_0_hidl::IMemtrack> MemtrackProxy::MemtrackHidlInstance() {
+    return V1_0_hidl::IMemtrack::getService();
+}
+
+std::shared_ptr<V1_aidl::IMemtrack> MemtrackProxy::MemtrackAidlInstance() {
+    const auto instance = std::string() + V1_aidl::IMemtrack::descriptor + "/default";
+    bool declared = AServiceManager_isDeclared(instance.c_str());
+    if (!declared) {
+        return nullptr;
+    }
+    ndk::SpAIBinder memtrack_binder =
+            ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str()));
+    return V1_aidl::IMemtrack::fromBinder(memtrack_binder);
+}
+
+bool MemtrackProxy::CheckUid(uid_t calling_uid) {
+    // Allow AID_SHELL for adb shell dumpsys meminfo
+    return calling_uid == AID_SYSTEM || calling_uid == AID_ROOT || calling_uid == AID_SHELL;
+}
+
+bool MemtrackProxy::CheckPid(pid_t calling_pid, pid_t request_pid) {
+    return calling_pid == request_pid;
+}
+
+MemtrackProxy::MemtrackProxy()
+      : memtrack_hidl_instance_(MemtrackProxy::MemtrackHidlInstance()),
+        memtrack_aidl_instance_(MemtrackProxy::MemtrackAidlInstance()) {}
+
+ndk::ScopedAStatus MemtrackProxy::getMemory(int pid, MemtrackType type,
+                                            std::vector<MemtrackRecord>* _aidl_return) {
+    if (pid < 0) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (!MemtrackProxy::CheckPid(AIBinder_getCallingPid(), pid) &&
+        !MemtrackProxy::CheckUid(AIBinder_getCallingUid())) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                EX_SECURITY,
+                "Only AID_ROOT, AID_SYSTEM and AID_SHELL can request getMemory() for PIDs other "
+                "than the calling PID");
+    }
+
+    if (type != MemtrackType::OTHER && type != MemtrackType::GL && type != MemtrackType::GRAPHICS &&
+        type != MemtrackType::MULTIMEDIA && type != MemtrackType::CAMERA) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+
+    _aidl_return->clear();
+
+    if (memtrack_aidl_instance_ ||
+        (memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance())) {
+        return memtrack_aidl_instance_->getMemory(pid, type, _aidl_return);
+    } else if (memtrack_hidl_instance_ ||
+               (memtrack_hidl_instance_ = MemtrackProxy::MemtrackHidlInstance())) {
+        ndk::ScopedAStatus aidl_status;
+
+        Return<void> ret = memtrack_hidl_instance_->getMemory(
+                pid, static_cast<V1_0_hidl::MemtrackType>(type),
+                [&_aidl_return, &aidl_status](V1_0_hidl::MemtrackStatus status,
+                                              hidl_vec<V1_0_hidl::MemtrackRecord> records) {
+                    switch (status) {
+                        case V1_0_hidl::MemtrackStatus::SUCCESS:
+                            aidl_status = ndk::ScopedAStatus::ok();
+                            break;
+                        case V1_0_hidl::MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
+                            [[fallthrough]];
+                        case V1_0_hidl::MemtrackStatus::TYPE_NOT_SUPPORTED:
+                            [[fallthrough]];
+                        default:
+                            aidl_status =
+                                    ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+                            return;
+                    }
+
+                    _aidl_return->resize(records.size());
+                    for (size_t i = 0; i < records.size(); i++) {
+                        if (!translate(records[i], &(*_aidl_return)[i])) {
+                            aidl_status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                                    EX_SERVICE_SPECIFIC,
+                                    "Failed to convert HIDL MemtrackRecord to AIDL");
+                            return;
+                        }
+                    }
+                });
+
+        // Check HIDL return
+        if (!ret.isOk()) {
+            const char* err_msg = "HIDL Memtrack::getMemory() failed";
+            aidl_status =
+                    ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC, err_msg);
+            LOG(ERROR) << err_msg << ": " << ret.description();
+        }
+
+        return aidl_status;
+    }
+
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+                                                            "Memtrack HAL service not available");
+}
+
+ndk::ScopedAStatus MemtrackProxy::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
+    if (!MemtrackProxy::CheckUid(AIBinder_getCallingUid())) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SECURITY,
+                "Only AID_ROOT, AID_SYSTEM and AID_SHELL can request getGpuDeviceInfo()");
+    }
+
+    _aidl_return->clear();
+
+    if (memtrack_aidl_instance_ ||
+        (memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance())) {
+        return memtrack_aidl_instance_->getGpuDeviceInfo(_aidl_return);
+    }
+
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+                                                            "Memtrack HAL service not available");
+}
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/services/memtrackproxy/include/memtrackproxy/MemtrackProxy.h b/services/memtrackproxy/include/memtrackproxy/MemtrackProxy.h
new file mode 100644
index 0000000..5ac1fbf
--- /dev/null
+++ b/services/memtrackproxy/include/memtrackproxy/MemtrackProxy.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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 <aidl/android/hardware/memtrack/BnMemtrack.h>
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/IMemtrack.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+
+using ::android::sp;
+
+namespace V1_0_hidl = ::android::hardware::memtrack::V1_0;
+namespace V1_aidl = ::aidl::android::hardware::memtrack;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+__attribute__((warn_unused_result)) bool translate(const V1_0_hidl::MemtrackRecord& in,
+                                                   V1_aidl::MemtrackRecord* out);
+
+class MemtrackProxy : public BnMemtrack {
+public:
+    MemtrackProxy();
+    ndk::ScopedAStatus getMemory(int pid, MemtrackType type,
+                                 std::vector<MemtrackRecord>* _aidl_return) override;
+    ndk::ScopedAStatus getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) override;
+
+private:
+    static sp<V1_0_hidl::IMemtrack> MemtrackHidlInstance();
+    static std::shared_ptr<V1_aidl::IMemtrack> MemtrackAidlInstance();
+    static bool CheckUid(uid_t calling_uid);
+    static bool CheckPid(pid_t calling_pid, pid_t request_pid);
+
+    sp<V1_0_hidl::IMemtrack> memtrack_hidl_instance_;
+    std::shared_ptr<V1_aidl::IMemtrack> memtrack_aidl_instance_;
+};
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/services/memtrackproxy/test/Android.bp b/services/memtrackproxy/test/Android.bp
new file mode 100644
index 0000000..e5ad8dc
--- /dev/null
+++ b/services/memtrackproxy/test/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2021 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.
+
+cc_test {
+    name: "memtrackproxy_test",
+    srcs: [
+        "MemtrackProxyTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libmemtrackproxy",
+        "android.hardware.memtrack-V1-ndk_platform",
+    ],
+    test_suites: ["general-tests"],
+    require_root: true,
+}
diff --git a/services/memtrackproxy/test/MemtrackProxyTest.cpp b/services/memtrackproxy/test/MemtrackProxyTest.cpp
new file mode 100644
index 0000000..16dfba0
--- /dev/null
+++ b/services/memtrackproxy/test/MemtrackProxyTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/IMemtrack.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+using aidl::android::hardware::memtrack::DeviceInfo;
+using aidl::android::hardware::memtrack::IMemtrack;
+using aidl::android::hardware::memtrack::MemtrackRecord;
+using aidl::android::hardware::memtrack::MemtrackType;
+
+class MemtrackProxyTest : public ::testing::Test {
+public:
+    virtual void SetUp() override {
+        const char* kMemtrackProxyService = "memtrack.proxy";
+        auto memtrackProxyBinder =
+                ndk::SpAIBinder(AServiceManager_waitForService(kMemtrackProxyService));
+        memtrack_proxy_ = IMemtrack::fromBinder(memtrackProxyBinder);
+        ASSERT_NE(memtrack_proxy_, nullptr);
+    }
+
+    std::shared_ptr<IMemtrack> memtrack_proxy_;
+};
+
+TEST_F(MemtrackProxyTest, GetMemoryForInvalidPid) {
+    int pid = -1;
+
+    for (MemtrackType type : ndk::enum_range<MemtrackType>()) {
+        std::vector<MemtrackRecord> records;
+
+        auto status = memtrack_proxy_->getMemory(pid, type, &records);
+
+        EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    }
+}
+
+TEST_F(MemtrackProxyTest, GetMemoryForCallingPid) {
+    int pid = getpid();
+
+    for (MemtrackType type : ndk::enum_range<MemtrackType>()) {
+        std::vector<MemtrackRecord> records;
+
+        auto status = memtrack_proxy_->getMemory(pid, type, &records);
+
+        EXPECT_TRUE(status.isOk());
+    }
+}
+
+TEST_F(MemtrackProxyTest, GetMemoryForOtherPid) {
+    int pid = 1;
+
+    for (MemtrackType type : ndk::enum_range<MemtrackType>()) {
+        std::vector<MemtrackRecord> records;
+
+        auto status = memtrack_proxy_->getMemory(pid, type, &records);
+
+        // Test is run as root
+        EXPECT_TRUE(status.isOk());
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}