Merge "Revert "Binder: support storing interface stability"" into stage-aosp-master
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 5bde7db..f7acaf1 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <fcntl.h>
-#include <libgen.h>
-
#include <android-base/file.h>
#include <android/os/BnDumpstate.h>
#include <android/os/BnDumpstateListener.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
+#include <fcntl.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <libgen.h>
#include <ziparchive/zip_archive.h>
+#include <fstream>
+#include <regex>
+
#include "dumpstate.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -44,6 +45,11 @@
namespace {
+struct SectionInfo {
+ std::string name;
+ int32_t size_bytes;
+};
+
sp<IDumpstate> GetDumpstateService() {
return android::interface_cast<IDumpstate>(
android::defaultServiceManager()->getService(String16("dumpstate")));
@@ -55,14 +61,79 @@
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
}
-} // namespace
+void GetEntry(const ZipArchiveHandle archive, const std::string_view entry_name, ZipEntry* data) {
+ int32_t e = FindEntry(archive, entry_name, data);
+ EXPECT_EQ(e, 0) << ErrorCodeString(e) << " entry name: " << entry_name;
+}
-struct SectionInfo {
- std::string name;
- status_t status;
- int32_t size_bytes;
- int32_t duration_ms;
-};
+// Extracts the main bugreport txt from the given archive and writes into output_fd.
+void ExtractBugreport(const ZipArchiveHandle* handle, int output_fd) {
+ // Read contents of main_entry.txt which is a single line indicating the name of the zip entry
+ // that contains the main bugreport txt.
+ ZipEntry main_entry;
+ GetEntry(*handle, "main_entry.txt", &main_entry);
+ std::string bugreport_txt_name;
+ bugreport_txt_name.resize(main_entry.uncompressed_length);
+ ExtractToMemory(*handle, &main_entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
+ main_entry.uncompressed_length);
+
+ // Read the main bugreport txt and extract to output_fd.
+ ZipEntry entry;
+ GetEntry(*handle, bugreport_txt_name, &entry);
+ ExtractEntryToFile(*handle, &entry, output_fd);
+}
+
+bool IsSectionStart(const std::string& line, std::string* section_name) {
+ static const std::regex kSectionStart = std::regex{"DUMP OF SERVICE (.*):"};
+ std::smatch match;
+ if (std::regex_match(line, match, kSectionStart)) {
+ *section_name = match.str(1);
+ return true;
+ }
+ return false;
+}
+
+bool IsSectionEnd(const std::string& line) {
+ // Not all lines that contain "was the duration of" is a section end, but all section ends do
+ // contain "was the duration of". The disambiguation can be done by the caller.
+ return (line.find("was the duration of") != std::string::npos);
+}
+
+// Extracts the zipped bugreport and identifies the sections.
+void ParseSections(const std::string& zip_path, std::vector<SectionInfo>* sections) {
+ // Open the archive
+ ZipArchiveHandle handle;
+ ASSERT_EQ(OpenArchive(zip_path.c_str(), &handle), 0);
+
+ // Extract the main entry to a temp file
+ TemporaryFile tmp_binary;
+ ASSERT_NE(-1, tmp_binary.fd);
+ ExtractBugreport(&handle, tmp_binary.fd);
+
+ // Read line by line and identify sections
+ std::ifstream ifs(tmp_binary.path, std::ifstream::in);
+ std::string line;
+ int section_bytes = 0;
+ std::string current_section_name;
+ while (std::getline(ifs, line)) {
+ std::string section_name;
+ if (IsSectionStart(line, §ion_name)) {
+ section_bytes = 0;
+ current_section_name = section_name;
+ } else if (IsSectionEnd(line)) {
+ if (!current_section_name.empty()) {
+ sections->push_back({current_section_name, section_bytes});
+ }
+ current_section_name = "";
+ } else if (!current_section_name.empty()) {
+ section_bytes += line.length();
+ }
+ }
+
+ CloseArchive(handle);
+}
+
+} // namespace
/**
* Listens to bugreport progress and updates the user by writing the progress to STDOUT. All the
@@ -107,11 +178,11 @@
return binder::Status::ok();
}
- binder::Status onSectionComplete(const ::std::string& name, int32_t status, int32_t size_bytes,
- int32_t duration_ms) override {
+ binder::Status onSectionComplete(const ::std::string& name, int32_t, int32_t size_bytes,
+ int32_t) override {
std::lock_guard<std::mutex> lock(lock_);
if (sections_.get() != nullptr) {
- sections_->push_back({name, status, size_bytes, duration_ms});
+ sections_->push_back({name, size_bytes});
}
return binder::Status::ok();
}
@@ -208,29 +279,30 @@
void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) {
ZipEntry entry;
- EXPECT_EQ(FindEntry(handle, filename, &entry), 0);
+ GetEntry(handle, filename, &entry);
EXPECT_GT(entry.uncompressed_length, minsize);
EXPECT_LT(entry.uncompressed_length, maxsize);
}
};
TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) {
- ZipEntry mainEntryLoc;
+ ZipEntry main_entry;
// contains main entry name file
- EXPECT_EQ(FindEntry(handle, "main_entry.txt", &mainEntryLoc), 0);
+ GetEntry(handle, "main_entry.txt", &main_entry);
- char* buf = new char[mainEntryLoc.uncompressed_length];
- ExtractToMemory(handle, &mainEntryLoc, (uint8_t*)buf, mainEntryLoc.uncompressed_length);
- delete[] buf;
+ std::string bugreport_txt_name;
+ bugreport_txt_name.resize(main_entry.uncompressed_length);
+ ExtractToMemory(handle, &main_entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
+ main_entry.uncompressed_length);
// contains main entry file
- FileExists(buf, 1000000U, 50000000U);
+ FileExists(bugreport_txt_name.c_str(), 1000000U, 50000000U);
}
TEST_F(ZippedBugReportContentsTest, ContainsVersion) {
ZipEntry entry;
// contains main entry name file
- EXPECT_EQ(FindEntry(handle, "version.txt", &entry), 0);
+ GetEntry(handle, "version.txt", &entry);
char* buf = new char[entry.uncompressed_length + 1];
ExtractToMemory(handle, &entry, (uint8_t*)buf, entry.uncompressed_length);
@@ -244,6 +316,10 @@
FileExists("dumpstate_board.txt", 100000U, 1000000U);
}
+TEST_F(ZippedBugReportContentsTest, ContainsProtoFile) {
+ FileExists("proto/activity.proto", 100000U, 1000000U);
+}
+
// Spot check on some files pulled from the file system
TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) {
// FS/proc/*/mountinfo size > 0
@@ -258,6 +334,11 @@
*/
class BugreportSectionTest : public Test {
public:
+ static void SetUpTestCase() {
+ ParseSections(ZippedBugreportGenerationTest::getZipFilePath(),
+ ZippedBugreportGenerationTest::sections.get());
+ }
+
int numMatches(const std::string& substring) {
int matches = 0;
for (auto const& section : *ZippedBugreportGenerationTest::sections) {
@@ -267,10 +348,11 @@
}
return matches;
}
+
void SectionExists(const std::string& sectionName, int minsize) {
for (auto const& section : *ZippedBugreportGenerationTest::sections) {
if (sectionName == section.name) {
- EXPECT_GE(section.size_bytes, minsize);
+ EXPECT_GE(section.size_bytes, minsize) << " for section:" << sectionName;
return;
}
}
@@ -278,71 +360,59 @@
}
};
-// Test all sections are generated without timeouts or errors
-TEST_F(BugreportSectionTest, GeneratedWithoutErrors) {
- for (auto const& section : *ZippedBugreportGenerationTest::sections) {
- EXPECT_EQ(section.status, 0) << section.name << " failed with status " << section.status;
- }
-}
-
TEST_F(BugreportSectionTest, Atleast3CriticalDumpsysSectionsGenerated) {
- int numSections = numMatches("DUMPSYS CRITICAL");
+ int numSections = numMatches("CRITICAL");
EXPECT_GE(numSections, 3);
}
TEST_F(BugreportSectionTest, Atleast2HighDumpsysSectionsGenerated) {
- int numSections = numMatches("DUMPSYS HIGH");
+ int numSections = numMatches("HIGH");
EXPECT_GE(numSections, 2);
}
TEST_F(BugreportSectionTest, Atleast50NormalDumpsysSectionsGenerated) {
- int allSections = numMatches("DUMPSYS");
- int criticalSections = numMatches("DUMPSYS CRITICAL");
- int highSections = numMatches("DUMPSYS HIGH");
+ int allSections = ZippedBugreportGenerationTest::sections->size();
+ int criticalSections = numMatches("CRITICAL");
+ int highSections = numMatches("HIGH");
int normalSections = allSections - criticalSections - highSections;
EXPECT_GE(normalSections, 50) << "Total sections less than 50 (Critical:" << criticalSections
<< "High:" << highSections << "Normal:" << normalSections << ")";
}
-TEST_F(BugreportSectionTest, Atleast1ProtoDumpsysSectionGenerated) {
- int numSections = numMatches("proto/");
- EXPECT_GE(numSections, 1);
-}
-
// Test if some critical sections are being generated.
TEST_F(BugreportSectionTest, CriticalSurfaceFlingerSectionGenerated) {
- SectionExists("DUMPSYS CRITICAL - SurfaceFlinger", /* bytes= */ 10000);
+ SectionExists("CRITICAL SurfaceFlinger", /* bytes= */ 10000);
}
TEST_F(BugreportSectionTest, ActivitySectionsGenerated) {
- SectionExists("DUMPSYS CRITICAL - activity", /* bytes= */ 5000);
- SectionExists("DUMPSYS - activity", /* bytes= */ 10000);
+ SectionExists("CRITICAL activity", /* bytes= */ 5000);
+ SectionExists("activity", /* bytes= */ 10000);
}
TEST_F(BugreportSectionTest, CpuinfoSectionGenerated) {
- SectionExists("DUMPSYS CRITICAL - cpuinfo", /* bytes= */ 1000);
+ SectionExists("CRITICAL cpuinfo", /* bytes= */ 1000);
}
TEST_F(BugreportSectionTest, WindowSectionGenerated) {
- SectionExists("DUMPSYS CRITICAL - window", /* bytes= */ 20000);
+ SectionExists("CRITICAL window", /* bytes= */ 20000);
}
TEST_F(BugreportSectionTest, ConnectivitySectionsGenerated) {
- SectionExists("DUMPSYS HIGH - connectivity", /* bytes= */ 5000);
- SectionExists("DUMPSYS - connectivity", /* bytes= */ 5000);
+ SectionExists("HIGH connectivity", /* bytes= */ 3000);
+ SectionExists("connectivity", /* bytes= */ 5000);
}
TEST_F(BugreportSectionTest, MeminfoSectionGenerated) {
- SectionExists("DUMPSYS HIGH - meminfo", /* bytes= */ 100000);
+ SectionExists("HIGH meminfo", /* bytes= */ 100000);
}
TEST_F(BugreportSectionTest, BatteryStatsSectionGenerated) {
- SectionExists("DUMPSYS - batterystats", /* bytes= */ 1000);
+ SectionExists("batterystats", /* bytes= */ 1000);
}
TEST_F(BugreportSectionTest, WifiSectionGenerated) {
- SectionExists("DUMPSYS - wifi", /* bytes= */ 100000);
+ SectionExists("wifi", /* bytes= */ 100000);
}
class DumpstateBinderTest : public Test {
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
index d936dbe..606477f 100644
--- a/cmds/servicemanager/Access.cpp
+++ b/cmds/servicemanager/Access.cpp
@@ -61,15 +61,21 @@
return gSehandle;
}
+struct AuditCallbackData {
+ const Access::CallingContext* context;
+ const std::string* tname;
+};
+
static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
- const Access::CallingContext* ad = reinterpret_cast<Access::CallingContext*>(data);
+ const AuditCallbackData* ad = reinterpret_cast<AuditCallbackData*>(data);
if (!ad) {
LOG(ERROR) << "No service manager audit data";
return 0;
}
- snprintf(buf, len, "pid=%d uid=%d", ad->debugPid, ad->uid);
+ snprintf(buf, len, "pid=%d uid=%d name=%s", ad->context->debugPid, ad->context->uid,
+ ad->tname->c_str());
return 0;
}
@@ -113,13 +119,20 @@
}
bool Access::canList(const CallingContext& ctx) {
- return actionAllowed(ctx, mThisProcessContext, "list");
+ return actionAllowed(ctx, mThisProcessContext, "list", "service_manager");
}
-bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm) {
+bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
+ const std::string& tname) {
const char* tclass = "service_manager";
- return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm, reinterpret_cast<void*>(const_cast<CallingContext*>((&sctx))));
+ AuditCallbackData data = {
+ .context = &sctx,
+ .tname = &tname,
+ };
+
+ return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm,
+ reinterpret_cast<void*>(&data));
}
bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
@@ -129,7 +142,7 @@
return false;
}
- bool allowed = actionAllowed(sctx, tctx, perm);
+ bool allowed = actionAllowed(sctx, tctx, perm, name);
freecon(tctx);
return allowed;
}
diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h
index 05a60d3..77c2cd4 100644
--- a/cmds/servicemanager/Access.h
+++ b/cmds/servicemanager/Access.h
@@ -45,7 +45,8 @@
virtual bool canList(const CallingContext& ctx);
private:
- bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm);
+ bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
+ const std::string& tname);
bool actionAllowedFromLookup(const CallingContext& sctx, const std::string& name,
const char *perm);
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index cfb86f0..7c45c77 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -465,7 +465,7 @@
void IPCThreadState::flushCommands()
{
- if (mProcess->mDriverFD <= 0)
+ if (mProcess->mDriverFD < 0)
return;
talkWithDriver(false);
// The flush could have caused post-write refcount decrements to have
@@ -618,7 +618,7 @@
int IPCThreadState::setupPolling(int* fd)
{
- if (mProcess->mDriverFD <= 0) {
+ if (mProcess->mDriverFD < 0) {
return -EBADF;
}
@@ -924,7 +924,7 @@
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
- if (mProcess->mDriverFD <= 0) {
+ if (mProcess->mDriverFD < 0) {
return -EBADF;
}
@@ -982,7 +982,7 @@
#else
err = INVALID_OPERATION;
#endif
- if (mProcess->mDriverFD <= 0) {
+ if (mProcess->mDriverFD < 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
@@ -1301,7 +1301,7 @@
if (self) {
self->flushCommands();
#if defined(__ANDROID__)
- if (self->mProcess->mDriverFD > 0) {
+ if (self->mProcess->mDriverFD >= 0) {
ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
}
#endif
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index cf3ef84..1537e69 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -54,9 +54,9 @@
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
- object_cleanup_func func);
- virtual void* findObject(const void* objectID) const;
- virtual void detachObject(const void* objectID);
+ object_cleanup_func func) final;
+ virtual void* findObject(const void* objectID) const final;
+ virtual void detachObject(const void* objectID) final;
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index b3a1d0b..e71541b 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -61,9 +61,9 @@
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
- object_cleanup_func func);
- virtual void* findObject(const void* objectID) const;
- virtual void detachObject(const void* objectID);
+ object_cleanup_func func) final;
+ virtual void* findObject(const void* objectID) const final;
+ virtual void detachObject(const void* objectID) final;
virtual BpBinder* remoteBinder();
diff --git a/services/nativeperms/.clang-format b/services/nativeperms/.clang-format
deleted file mode 100644
index 6006e6f..0000000
--- a/services/nativeperms/.clang-format
+++ /dev/null
@@ -1,13 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: Inline
-AllowShortIfStatementsOnASingleLine: true
-AllowShortLoopsOnASingleLine: true
-BinPackArguments: true
-BinPackParameters: true
-ColumnLimit: 80
-CommentPragmas: NOLINT:.*
-ContinuationIndentWidth: 8
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
diff --git a/services/nativeperms/Android.bp b/services/nativeperms/Android.bp
deleted file mode 100644
index cbc7d66..0000000
--- a/services/nativeperms/Android.bp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2016 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_binary {
- name: "nativeperms",
- srcs: [
- "nativeperms.cpp",
- "android/os/IPermissionController.aidl",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- shared_libs: [
- "libbinder",
- "libbrillo",
- "libbrillo-binder",
- "libchrome",
- "libutils",
- ],
- init_rc: ["nativeperms.rc"],
-}
diff --git a/services/nativeperms/android/os/IPermissionController.aidl b/services/nativeperms/android/os/IPermissionController.aidl
deleted file mode 100644
index 89db85c..0000000
--- a/services/nativeperms/android/os/IPermissionController.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* //device/java/android/android/os/IPowerManager.aidl
-**
-** Copyright 2007, 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.os;
-
-/** @hide */
-interface IPermissionController {
- boolean checkPermission(String permission, int pid, int uid);
- String[] getPackagesForUid(int uid);
- boolean isRuntimePermission(String permission);
-}
diff --git a/services/nativeperms/android/os/README b/services/nativeperms/android/os/README
deleted file mode 100644
index e414499..0000000
--- a/services/nativeperms/android/os/README
+++ /dev/null
@@ -1,4 +0,0 @@
-IPermissionController.aidl in this directory is a verbatim copy of
-https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/IPermissionController.aidl,
-because some Brillo manifests do not currently include the frameworks/base repo.
-TODO(jorgelo): Figure out a way to use the .aidl file in frameworks/base.
diff --git a/services/nativeperms/nativeperms.cpp b/services/nativeperms/nativeperms.cpp
deleted file mode 100644
index 7f03bed..0000000
--- a/services/nativeperms/nativeperms.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2016 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 <base/at_exit.h>
-#include <base/logging.h>
-#include <base/message_loop/message_loop.h>
-#include <binder/IServiceManager.h>
-#include <binder/Status.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/message_loops/base_message_loop.h>
-#include <brillo/syslog_logging.h>
-#include <utils/String16.h>
-
-#include "android/os/BnPermissionController.h"
-
-namespace {
-static android::String16 serviceName("permission");
-}
-
-namespace android {
-
-class PermissionService : public android::os::BnPermissionController {
- public:
- ::android::binder::Status checkPermission(
- const ::android::String16& permission, int32_t pid, int32_t uid,
- bool* _aidl_return) {
- (void)permission;
- (void)pid;
- (void)uid;
- *_aidl_return = true;
- return binder::Status::ok();
- }
-
- ::android::binder::Status getPackagesForUid(
- int32_t uid, ::std::vector<::android::String16>* _aidl_return) {
- (void)uid;
- // Brillo doesn't currently have installable packages.
- if (_aidl_return) {
- _aidl_return->clear();
- }
- return binder::Status::ok();
- }
-
- ::android::binder::Status isRuntimePermission(
- const ::android::String16& permission, bool* _aidl_return) {
- (void)permission;
- // Brillo doesn't currently have runtime permissions.
- *_aidl_return = false;
- return binder::Status::ok();
- }
-};
-
-} // namespace android
-
-int main() {
- base::AtExitManager atExitManager;
- brillo::InitLog(brillo::kLogToSyslog);
- // Register the service with servicemanager.
- android::status_t status = android::defaultServiceManager()->addService(
- serviceName, new android::PermissionService());
- CHECK(status == android::OK) << "Failed to get IPermissionController "
- "binder from servicemanager.";
-
- // Create a message loop.
- base::MessageLoopForIO messageLoopForIo;
- brillo::BaseMessageLoop messageLoop{&messageLoopForIo};
-
- // Initialize a binder watcher.
- brillo::BinderWatcher watcher(&messageLoop);
- watcher.Init();
-
- // Run the message loop.
- messageLoop.Run();
-}
diff --git a/services/nativeperms/nativeperms.rc b/services/nativeperms/nativeperms.rc
deleted file mode 100644
index 704c0a2..0000000
--- a/services/nativeperms/nativeperms.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service nativeperms /system/bin/nativeperms
- class main
- user system
- group system