Merge "libbinder_ndk: expose updatable-via-apex"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index f54f132..e66bca0 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -28,9 +28,6 @@
"include-filter": "*CropLatchingTest.*"
},
{
- "include-filter": "*ChildLayerTest.*"
- },
- {
"include-filter": "*ScreenCaptureTest.*"
},
{
@@ -56,9 +53,6 @@
},
{
"include-filter": "*RefreshRateOverlayTest.*"
- },
- {
- "exclude-filter": "*ChildLayerTest#ChildrenSurviveParentDestruction"
}
]
},
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index c1ae5b4..ee1c63a 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -170,6 +170,7 @@
#define RECOVERY_DIR "/cache/recovery"
#define RECOVERY_DATA_DIR "/data/misc/recovery"
#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
+#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
#define LOGPERSIST_DATA_DIR "/data/misc/logd"
#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
@@ -234,6 +235,7 @@
// task and the log title of the duration report.
static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
+static const std::string DUMP_NETSTATS_PROTO_TASK = "DUMP NETSTATS PROTO";
static const std::string DUMP_HALS_TASK = "DUMP HALS";
static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
@@ -1041,6 +1043,26 @@
}
}
+static void DumpNetstatsProto() {
+ const std::string path = ds.bugreport_internal_dir_ + "/tmp_netstats_proto";
+ auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
+ if (fd < 0) {
+ MYLOGE("Could not open %s to dump netstats proto.\n", path.c_str());
+ return;
+ }
+ RunCommandToFd(fd, "", {"dumpsys", "netstats", "--proto"},
+ CommandOptions::WithTimeout(120).Build());
+ bool empty = 0 == lseek(fd, 0, SEEK_END);
+ if (!empty) {
+ ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "netstats" + kProtoExt,
+ path);
+ } else {
+ unlink(path.c_str());
+ }
+}
+
static void MaybeAddSystemTraceToZip() {
// This function copies into the .zip the system trace that was snapshotted
// by the early call to MaybeSnapshotSystemTrace(), if any background
@@ -1576,7 +1598,8 @@
DurationReporter duration_reporter("DUMPSTATE");
// Enqueue slow functions into the thread pool, if the parallel run is enabled.
- std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins;
+ std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins,
+ dump_netstats_report;
if (ds.dump_pool_) {
// Pool was shutdown in DumpstateDefaultAfterCritical method in order to
// drop root user. Restarts it with two threads for the parallel run.
@@ -1585,6 +1608,8 @@
dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
dump_incident_report = ds.dump_pool_->enqueueTask(
DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
+ dump_netstats_report = ds.dump_pool_->enqueueTask(
+ DUMP_NETSTATS_PROTO_TASK, &DumpNetstatsProto);
dump_board = ds.dump_pool_->enqueueTaskWithFd(
DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
@@ -1779,6 +1804,13 @@
dump_frozen_cgroupfs();
if (ds.dump_pool_) {
+ WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_netstats_report));
+ } else {
+ RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_NETSTATS_PROTO_TASK,
+ DumpNetstatsProto);
+ }
+
+ if (ds.dump_pool_) {
WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
} else {
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
@@ -1828,6 +1860,7 @@
ds.AddDir(RECOVERY_DIR, true);
ds.AddDir(RECOVERY_DATA_DIR, true);
ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
+ ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
ds.AddDir(LOGPERSIST_DATA_DIR, false);
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(PROFILE_DATA_DIR_CUR, true);
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 6ef41e3..3b589dc 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -23,6 +23,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/macros.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
@@ -52,22 +53,7 @@
constexpr int kTimeoutMs = 60000;
-// TODO(calin): try to dedup this code.
-#if defined(__arm__)
-static const std::string kRuntimeIsa = "arm";
-#elif defined(__aarch64__)
-static const std::string kRuntimeIsa = "arm64";
-#elif defined(__mips__) && !defined(__LP64__)
-static const std::string kRuntimeIsa = "mips";
-#elif defined(__mips__) && defined(__LP64__)
-static const std::string kRuntimeIsa = "mips64";
-#elif defined(__i386__)
-static const std::string kRuntimeIsa = "x86";
-#elif defined(__x86_64__)
-static const std::string kRuntimeIsa = "x86_64";
-#else
-static const std::string kRuntimeIsa = "none";
-#endif
+static const std::string kRuntimeIsa = ABI_STRING;
int get_property(const char *key, char *value, const char *default_value) {
return property_get(key, value, default_value);
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index a831d1b..c1a04dd 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -111,9 +111,7 @@
};
int main(int argc, char** argv) {
-#ifdef __ANDROID_RECOVERY__
android::base::InitLogging(argv, android::base::KernelLogger);
-#endif
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 6b35265..3bd6db5 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -3,6 +3,7 @@
user system
group system readproc
critical
+ file /dev/kmsg w
onrestart setprop servicemanager.ready false
onrestart restart apexd
onrestart restart audioserver
diff --git a/cmds/servicemanager/vndservicemanager.rc b/cmds/servicemanager/vndservicemanager.rc
index c9305a1..80af1d1 100644
--- a/cmds/servicemanager/vndservicemanager.rc
+++ b/cmds/servicemanager/vndservicemanager.rc
@@ -2,6 +2,7 @@
class core
user system
group system readproc
+ file /dev/kmsg w
task_profiles ServiceCapacityLow
onrestart class_restart main
onrestart class_restart hal
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index 5baa4d7..883ae31 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -24,21 +24,21 @@
// Starts an RPC server on a given port and a given root IBinder object.
// This function sets up the server and joins before returning.
-bool RunRpcServer(AIBinder* service, unsigned int port);
+bool RunVsockRpcServer(AIBinder* service, unsigned int port);
// Starts an RPC server on a given port and a given root IBinder object.
// This function sets up the server, calls readyCallback with a given param, and
// then joins before returning.
-bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
- void* param);
+bool RunVsockRpcServerCallback(AIBinder* service, unsigned int port,
+ void (*readyCallback)(void* param), void* param);
// Starts an RPC server on a given port and a given root IBinder factory.
-// RunRpcServerWithFactory acts like RunRpcServerCallback, but instead of
+// RunVsockRpcServerWithFactory acts like RunVsockRpcServerCallback, but instead of
// assigning single root IBinder object to all connections, factory is called
// whenever a client connects, making it possible to assign unique IBinder
// object to each client.
-bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
- void* factoryContext, unsigned int port);
+bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
+ void* factoryContext, unsigned int port);
AIBinder* RpcClient(unsigned int cid, unsigned int port);
@@ -50,5 +50,4 @@
// param will be passed to requestFd. Callers can use param to pass contexts to
// the requestFd function.
AIBinder* RpcPreconnectedClient(int (*requestFd)(void* param), void* param);
-
}
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index a3d42b7..49686e1 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -30,8 +30,8 @@
extern "C" {
-bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
- void* factoryContext, unsigned int port) {
+bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
+ void* factoryContext, unsigned int port) {
auto server = RpcServer::make();
if (status_t status = server->setupVsockServer(port); status != OK) {
LOG(ERROR) << "Failed to set up vsock server with port " << port
@@ -52,8 +52,8 @@
return true;
}
-bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
- void* param) {
+bool RunVsockRpcServerCallback(AIBinder* service, unsigned int port,
+ void (*readyCallback)(void* param), void* param) {
auto server = RpcServer::make();
if (status_t status = server->setupVsockServer(port); status != OK) {
LOG(ERROR) << "Failed to set up vsock server with port " << port
@@ -70,8 +70,8 @@
return true;
}
-bool RunRpcServer(AIBinder* service, unsigned int port) {
- return RunRpcServerCallback(service, port, nullptr, nullptr);
+bool RunVsockRpcServer(AIBinder* service, unsigned int port) {
+ return RunVsockRpcServerCallback(service, port, nullptr, nullptr);
}
AIBinder* RpcClient(unsigned int cid, unsigned int port) {
diff --git a/libs/binder/libbinder_rpc_unstable.map.txt b/libs/binder/libbinder_rpc_unstable.map.txt
index e856569..15b6ee9 100644
--- a/libs/binder/libbinder_rpc_unstable.map.txt
+++ b/libs/binder/libbinder_rpc_unstable.map.txt
@@ -1,7 +1,7 @@
LIBBINDER_RPC_UNSTABLE_SHIM { # platform-only
global:
- RunRpcServer;
- RunRpcServerCallback;
+ RunVsockRpcServer;
+ RunVsockRpcServerCallback;
RpcClient;
RpcPreconnectedClient;
local:
diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs
index a5eea61..fb6b90c 100644
--- a/libs/binder/rust/rpcbinder/src/lib.rs
+++ b/libs/binder/rust/rpcbinder/src/lib.rs
@@ -23,4 +23,4 @@
get_preconnected_rpc_interface, get_preconnected_rpc_service, get_vsock_rpc_interface,
get_vsock_rpc_service,
};
-pub use server::{run_rpc_server, run_rpc_server_with_factory};
+pub use server::{run_vsock_rpc_server, run_vsock_rpc_server_with_factory};
diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs
index aeb23c6..8009297 100644
--- a/libs/binder/rust/rpcbinder/src/server.rs
+++ b/libs/binder/rust/rpcbinder/src/server.rs
@@ -30,7 +30,7 @@
/// The current thread is joined to the binder thread pool to handle incoming messages.
///
/// Returns true if the server has shutdown normally, false if it failed in some way.
-pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
+pub fn run_vsock_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
where
F: FnOnce(),
{
@@ -52,10 +52,10 @@
// SAFETY: Service ownership is transferring to the server and won't be valid afterward.
// Plus the binder objects are threadsafe.
- // RunRpcServerCallback does not retain a reference to `ready_callback` or `param`; it only
+ // RunVsockRpcServerCallback does not retain a reference to `ready_callback` or `param`; it only
// uses them before it returns, which is during the lifetime of `self`.
unsafe {
- binder_rpc_unstable_bindgen::RunRpcServerCallback(
+ binder_rpc_unstable_bindgen::RunVsockRpcServerCallback(
service,
port,
Some(Self::ready_callback),
@@ -69,7 +69,7 @@
}
unsafe extern "C" fn ready_callback(param: *mut raw::c_void) {
- // SAFETY: This is only ever called by `RunRpcServerCallback`, within the lifetime of the
+ // SAFETY: This is only ever called by `RunVsockRpcServerCallback`, within the lifetime of the
// `ReadyNotifier`, with `param` taking the value returned by `as_void_ptr` (so a properly
// aligned non-null pointer to an initialized instance).
let ready_notifier = param as *mut Self;
@@ -91,7 +91,7 @@
/// The current thread is joined to the binder thread pool to handle incoming messages.
///
/// Returns true if the server has shutdown normally, false if it failed in some way.
-pub fn run_rpc_server_with_factory(
+pub fn run_vsock_rpc_server_with_factory(
port: u32,
mut factory: impl FnMut(u32) -> Option<SpIBinder> + Send + Sync,
) -> bool {
@@ -100,18 +100,22 @@
let mut factory_ref: RpcServerFactoryRef = &mut factory;
let context = &mut factory_ref as *mut RpcServerFactoryRef as *mut raw::c_void;
- // SAFETY: `factory_wrapper` is only ever called by `RunRpcServerWithFactory`, with context
+ // SAFETY: `factory_wrapper` is only ever called by `RunVsockRpcServerWithFactory`, with context
// taking the pointer value above (so a properly aligned non-null pointer to an initialized
// `RpcServerFactoryRef`), within the lifetime of `factory_ref` (i.e. no more calls will be made
- // after `RunRpcServerWithFactory` returns).
+ // after `RunVsockRpcServerWithFactory` returns).
unsafe {
- binder_rpc_unstable_bindgen::RunRpcServerWithFactory(Some(factory_wrapper), context, port)
+ binder_rpc_unstable_bindgen::RunVsockRpcServerWithFactory(
+ Some(factory_wrapper),
+ context,
+ port,
+ )
}
}
unsafe extern "C" fn factory_wrapper(cid: u32, context: *mut raw::c_void) -> *mut AIBinder {
// SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by
- // `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is
+ // `run_vsock_rpc_server_with_factory`, and we are still within the lifetime of the value it is
// pointing to.
let factory_ptr = context as *mut RpcServerFactoryRef;
let factory = factory_ptr.as_mut().unwrap();
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index a6585c5..067ce17 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -208,5 +208,5 @@
cmdline = std::string(cmdline.c_str());
return cmdline == "zygote" || cmdline == "zygote64" || cmdline == "usap32" ||
- cmdline == "usap64";
+ cmdline == "usap64" || cmdline == "webview_zygote";
}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 0f771a9..98d9b94 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -155,6 +155,8 @@
],
defaults: [
+ "android.hardware.graphics.allocator-ndk_shared",
+ "android.hardware.graphics.common-ndk_shared",
"libui-defaults",
// Uncomment the following line to enable VALIDATE_REGIONS traces
//defaults: ["libui-validate-regions-defaults"],
@@ -164,8 +166,6 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.allocator-V1-ndk",
- "android.hardware.graphics.common-V3-ndk",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
@@ -183,7 +183,6 @@
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.common-V3-ndk",
"android.hardware.graphics.mapper@4.0",
"libgralloctypes",
],
diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp
index 83c250a..2af51a7 100644
--- a/libs/vibrator/Android.bp
+++ b/libs/vibrator/Android.bp
@@ -21,31 +21,8 @@
default_applicable_licenses: ["frameworks_native_license"],
}
-cc_library {
- name: "libvibrator",
- vendor_available: true,
- double_loadable: true,
-
- shared_libs: [
- "libbinder",
- "liblog",
- "libutils",
- ],
-
- header_libs: [
- "libaudio_system_headers",
- ],
-
- aidl: {
- include_dirs: ["frameworks/base/core/java"],
- local_include_dirs: ["include/"],
- export_aidl_headers: true,
- },
-
- srcs: [
- ":libvibrator_aidl",
- "*.cpp",
- ],
+cc_defaults {
+ name: "libvibrator_defaults",
cflags: [
"-Wall",
@@ -64,3 +41,54 @@
},
},
}
+
+cc_library {
+ name: "libvibrator",
+ defaults: ["libvibrator_defaults"],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+
+ whole_static_libs: [
+ "libvibratorutils",
+ ],
+
+ header_libs: [
+ "libaudio_system_headers",
+ ],
+
+ aidl: {
+ include_dirs: ["frameworks/base/core/java"],
+ local_include_dirs: ["include/"],
+ export_aidl_headers: true,
+ },
+
+ srcs: [
+ ":libvibrator_aidl",
+ "ExternalVibration.cpp",
+ ],
+}
+
+cc_library {
+ name: "libvibratorutils",
+ defaults: ["libvibrator_defaults"],
+
+ vendor_available: true,
+ double_loadable: true,
+
+ shared_libs: [
+ "libutils",
+ ],
+
+ srcs: [
+ "ExternalVibrationUtils.cpp",
+ ],
+
+ visibility: [
+ "//frameworks/native/libs/vibrator",
+ "//frameworks/av/media/libeffects/hapticgenerator",
+ ],
+}
diff --git a/libs/vibrator/ExternalVibration.cpp b/libs/vibrator/ExternalVibration.cpp
index f6fc19e..ec90645 100644
--- a/libs/vibrator/ExternalVibration.cpp
+++ b/libs/vibrator/ExternalVibration.cpp
@@ -15,11 +15,22 @@
*/
#include <vibrator/ExternalVibration.h>
+#include <vibrator/ExternalVibrationUtils.h>
+#include <android/os/IExternalVibratorService.h>
#include <binder/Parcel.h>
#include <log/log.h>
#include <utils/Errors.h>
+
+// To guarantee if HapticScale enum has the same value as IExternalVibratorService
+static_assert(static_cast<int>(android::os::HapticScale::MUTE) == static_cast<int>(android::os::IExternalVibratorService::SCALE_MUTE));
+static_assert(static_cast<int>(android::os::HapticScale::VERY_LOW) == static_cast<int>(android::os::IExternalVibratorService::SCALE_VERY_LOW));
+static_assert(static_cast<int>(android::os::HapticScale::LOW) == static_cast<int>(android::os::IExternalVibratorService::SCALE_LOW));
+static_assert(static_cast<int>(android::os::HapticScale::NONE) == static_cast<int>(android::os::IExternalVibratorService::SCALE_NONE));
+static_assert(static_cast<int>(android::os::HapticScale::HIGH) == static_cast<int>(android::os::IExternalVibratorService::SCALE_HIGH));
+static_assert(static_cast<int>(android::os::HapticScale::VERY_HIGH) == static_cast<int>(android::os::IExternalVibratorService::SCALE_VERY_HIGH));
+
void writeAudioAttributes(const audio_attributes_t& attrs, android::Parcel* out) {
out->writeInt32(attrs.usage);
out->writeInt32(attrs.content_type);
diff --git a/libs/vibrator/include/vibrator/ExternalVibrationUtils.h b/libs/vibrator/include/vibrator/ExternalVibrationUtils.h
index 84357fc..c588bfd 100644
--- a/libs/vibrator/include/vibrator/ExternalVibrationUtils.h
+++ b/libs/vibrator/include/vibrator/ExternalVibrationUtils.h
@@ -17,17 +17,17 @@
#ifndef ANDROID_EXTERNAL_VIBRATION_UTILS_H
#define ANDROID_EXTERNAL_VIBRATION_UTILS_H
-#include <android/os/IExternalVibratorService.h>
-
namespace android::os {
+// Copied from frameworks/base/core/java/android/os/IExternalVibratorService.aidl
+// The values are checked in ExternalVibration.cpp
enum class HapticScale {
- MUTE = IExternalVibratorService::SCALE_MUTE,
- VERY_LOW = IExternalVibratorService::SCALE_VERY_LOW,
- LOW = IExternalVibratorService::SCALE_LOW,
- NONE = IExternalVibratorService::SCALE_NONE,
- HIGH = IExternalVibratorService::SCALE_HIGH,
- VERY_HIGH = IExternalVibratorService::SCALE_VERY_HIGH,
+ MUTE = -100,
+ VERY_LOW = -2,
+ LOW = -1,
+ NONE = 0,
+ HIGH = 1,
+ VERY_HIGH = 2,
};
bool isValidHapticScale(HapticScale scale);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e9fbf6e..e234ed0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -7564,7 +7564,7 @@
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) &&
+ if ((uid != AID_GRAPHICS) && (uid != AID_SYSTEM) &&
!PermissionCache::checkPermission(sControlDisplayBrightness, pid, uid)) {
ALOGE("Permission Denial: can't control brightness pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;