diff --git a/codeql-custom-queries-java/android/avoid-sensor-manager-leak.expected b/codeql-custom-queries-java/android/avoid-sensor-manager-leak.expected new file mode 100644 index 0000000..87d0555 --- /dev/null +++ b/codeql-custom-queries-java/android/avoid-sensor-manager-leak.expected @@ -0,0 +1,4 @@ +| avoid-sensor-manager-leak.java:20:9:20:56 | registerListener(...) | Call unregisterListener() to match this registerListener() on 'SensorManager' to avoid unnecessary battery drain. | +| avoid-sensor-manager-leak.java:26:9:26:56 | registerListener(...) | Call unregisterListener() to match this registerListener() on 'SensorManager' to avoid unnecessary battery drain. | +| avoid-sensor-manager-leak.java:32:9:32:56 | registerListener(...) | Call unregisterListener() to match this registerListener() on 'SensorManager' to avoid unnecessary battery drain. | +| avoid-sensor-manager-leak.java:33:9:33:56 | registerListener(...) | Call unregisterListener() to match this registerListener() on 'SensorManager' to avoid unnecessary battery drain. | diff --git a/codeql-custom-queries-java/android/avoid-sensor-manager-leak.java b/codeql-custom-queries-java/android/avoid-sensor-manager-leak.java new file mode 100644 index 0000000..6a0a21f --- /dev/null +++ b/codeql-custom-queries-java/android/avoid-sensor-manager-leak.java @@ -0,0 +1,53 @@ +class SensorManager { + void registerListener(Object listener, Object sensor, int delay) { + } + + void unregisterListener(Object listener) { + } +} + +class Sensor { + static final int TYPE_ACCELEROMETER = 1; + static final int TYPE_GYROSCOPE = 4; + static final int TYPE_LIGHT = 5; +} + +// 🚫 Noncompliant - registerListener without unregisterListener +class NoncompliantSensorLeak { + + void startAccelerometer() { + SensorManager sManager = new SensorManager(); + sManager.registerListener(null, new Sensor(), 1); // $ Alert + // missing sManager.unregisterListener() + } + + void startGyroscope() { + SensorManager sManager = new SensorManager(); + sManager.registerListener(null, new Sensor(), 1); // $ Alert + // missing sManager.unregisterListener() + } + + void startMultipleSensors() { + SensorManager sManager = new SensorManager(); + sManager.registerListener(null, new Sensor(), 1); // $ Alert + sManager.registerListener(null, new Sensor(), 1); // $ Alert + // missing sManager.unregisterListener() + } +} + +// ✅ Compliant - registerListener with matching unregisterListener +class CompliantSensorUsage { + + void startAccelerometer() { + SensorManager sManager = new SensorManager(); + sManager.registerListener(null, new Sensor(), 1); // OK + sManager.unregisterListener(null); + } + + void startMultipleSensors() { + SensorManager sManager = new SensorManager(); + sManager.registerListener(null, new Sensor(), 1); // OK + sManager.registerListener(null, new Sensor(), 1); // OK + sManager.unregisterListener(null); + } +} diff --git a/codeql-custom-queries-java/android/avoid-sensor-manager-leak.ql b/codeql-custom-queries-java/android/avoid-sensor-manager-leak.ql new file mode 100644 index 0000000..47117d2 --- /dev/null +++ b/codeql-custom-queries-java/android/avoid-sensor-manager-leak.ql @@ -0,0 +1,23 @@ +/** + * @name Avoid SensorManager listener leak + * @description Calling SensorManager.registerListener() without a matching unregisterListener() causes the sensor to keep processing data during idle states, draining battery within hours. + * @kind problem + * @problem.severity warning + * @precision medium + * @id java/android/avoid-sensor-manager-leak + * @link https://green-code-initiative.org/rules#id:GCI514 + * @tags android + */ + +import java + +from MethodCall register +where + register.getMethod().getName() = "registerListener" and + register.getQualifier().(VarAccess).getType().(RefType).getName() = "SensorManager" and + not exists(MethodCall unregister | + unregister.getMethod().getName() = "unregisterListener" and + unregister.getEnclosingCallable() = register.getEnclosingCallable() + ) +select register, + "Call unregisterListener() to match this registerListener() on 'SensorManager' to avoid unnecessary battery drain." \ No newline at end of file