Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/migrate mobile rule #237

Merged
merged 11 commits into from
Oct 28, 2023
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- [ios#3](https://github.com/green-code-initiative/ecoCode-ios/issues/3) Move iOS rules into centralized rules repository
- [android#67](https://github.com/green-code-initiative/ecoCode-android/issues/67) Move Android rules into centralized rules repository
- [#216](https://github.com/green-code-initiative/ecoCode/issues/216) Upgrade rule EC2 for Java : Multiple if-else statement improvment
- [#106](https://github.com/green-code-initiative/ecoCode/issues/106) Upgrade RULES.md : rule EC67 not relevant neither for Python nor Rust
- [#225](https://github.com/green-code-initiative/ecoCode/pull/225) Upgrade licence system and licence headers of Java files
Expand Down
42 changes: 41 additions & 1 deletion ecocode-rules-specifications/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<artifactId>ecocode-rules-specifications</artifactId>

<name>ecoCode Rules Specifications repository</name>
<description>Repository that contains the specifications of every static-analysis rules available in ecoCode plugins.</description>
<description>Repository that contains the specifications of every static-analysis rules available in ecoCode
plugins.
</description>
<url>https://github.com/green-code-initiative/ecoCode/tree/main/ecocode-rules-specifications</url>

<dependencies>
Expand Down Expand Up @@ -147,6 +149,20 @@
</fileset>
<flattenmapper />
</copy>
<copy todir="${project.build.outputDirectory}/io/ecocode/rules/swift">
<fileset dir="${project.build.directory}/rules">
<include name="*/swift/EC*.html" />
<include name="*/EC*.json" />
</fileset>
<flattenmapper />
</copy>
<copy todir="${project.build.outputDirectory}/io/ecocode/rules/xml">
<fileset dir="${project.build.directory}/rules">
<include name="*/xml/EC*.html" />
<include name="*/EC*.json" />
</fileset>
<flattenmapper />
</copy>
</target>
</configuration>
</execution>
Expand Down Expand Up @@ -228,6 +244,30 @@
</descriptors>
</configuration>
</execution>
<execution>
<id>assembly-swift</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/swift.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>assembly-xml</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/xml.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
Expand Down
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/assembly/swift.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 https://maven.apache.org/xsd/assembly-2.1.1.xsd">
<id>swift</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<includes>
<include>io/ecocode/rules/swift/*.*</include>
</includes>
<outputDirectory/>
</fileSet>
</fileSets>
</assembly>
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/assembly/xml.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 https://maven.apache.org/xsd/assembly-2.1.1.xsd">
<id>xml</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<includes>
<include>io/ecocode/rules/xml/*.*</include>
</includes>
<outputDirectory/>
</fileSet>
</fileSets>
</assembly>
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC500/EC500.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Batch: Sensor Coalesce",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "20min"
},
"tags": [
"batch",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.4",
"defaultSeverity": "Minor"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
With `SensorManager#registerListener(SensorEventListener, Sensor, int)` the events are delivered as soon as possible.

Instead, `SensorManager#registerListener(SensorEventListener, Sensor, int, int maxReportLatencyUs)` allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The events can be stored in the hardware FIFO up to `maxReportLatencyUs` microseconds.

Once one of the events in the FIFO needs to be reported, all the events in the FIFO are reported sequentially. Setting `maxReportLatencyUs` to a positive value allows to reduce the number of interrupts the AP (Application Processor) receives, hence reducing power consumption, as the AP can switch to a lower power state while the sensor is capturing the data.

## Noncompliant Code Example

```java
SensorEventListener sensorEventListener;
SensorManager sensorManager;
Sensor sensor;

sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
```

## Compliant Code Example

```java
SensorEventListener sensorEventListener;
SensorManager sensorManager;
Sensor sensor;

sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL, 200000);
```
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC501/EC501.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Batch: Job Coalesce",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "3h"
},
"tags": [
"batch",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.4",
"defaultSeverity": "Minor"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
The Android 5.0 Lollipop (API 21) release introduces a job scheduler API via the Job Scheduler class.

Compared to a custom Sync Adapter or the alarm manager, the Job Scheduler supports batch scheduling of jobs.

The Android system can combine jobs so that battery consumption is reduced.

## Noncompliant Code Example

```java
void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pendingIntent);
}

Alarm alarm = new Alarm();
alarm.setAlarm(this);
```

## Compliant Code Example

```java
JobInfo info = new JobInfo.Builder(123, COMPONENT_NAME)
.setRequiresCharging(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.setPeriodic(10 * 60 * 1000)
.build();
JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.schedule(info);
```
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC502/EC502.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Bottleneck: Internet In The Loop",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "3h"
},
"tags": [
"optimized-api",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.2",
"defaultSeverity": "Critical"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Opening and closing internet connection continuously is extremely battery-inefficient since HTTP exchange is the most consuming operation of the network. This bug typically occurs when one obtain a new `HttpURLConnection` by calling `URL#openConnection()` within a loop control structure (while, for, do-while, for-each).

Also, this bad practice must be early prevented because it is the root of another evil that consists in polling data at regular intervals, instead of using push notifications to save a lot of battery power.

## Noncompliant Code Example

```java
for (int val : myArray) {
URL.openConnection();
}
```
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC503/EC503.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Bottleneck: Wifi Multicast Lock",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "20min"
},
"tags": [
"bottleneck",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.6",
"defaultSeverity": "Minor"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Normally the Wi-Fi stack filters out packets not explicitly addressed to the device. Acquiring a Multicast Lock with `WifiManager.MulticastLock.acquire()` will cause the stack to receive packets addressed to multicast addresses.

Processing these extra packets can cause a noticeable battery drain and must be disabled when not needed with to a call to `WifiManager.MulticastLock.release()`.

## Noncompliant Code Example

```java
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock lock = wifiManager.createMulticastLock("tag");
lock.acquire();
```

## Compliant Code Example

```java
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock lock = wifiManager.createMulticastLock("tag");
lock.acquire();
lock.release()
```
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC504/EC504.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Bottleneck: Uncompressed Data Transmission",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "10min"
},
"tags": [
"bottleneck",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.4",
"defaultSeverity": "Minor"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Transmitting a file over a network infrastructure without compressing it consumes more energy than with compression. More precisely, energy efficiency is improved in case the data is compressed at least by 10%, transmitted and decompressed at the other network node. From the Android client side, it means making a post HTTP request using a `GZIPOutputStream` instead of the classical OutputStream, along with the `HttpURLConnection` object.

## Noncompliant Code Example

```java
Url url = new Url("https://www.ecocode.io/");
HttpsUrlConnection con = (HttpsURLConnection) url.openConnection();
OutputStream stream = con.getOutputStream();
```

## Compliant Code Example

```java
Url url = new Url("https://www.ecocode.io/");
HttpsUrlConnection con = (HttpsURLConnection) url.openConnection();
OutputStream stream = new GZIPOutputStream(con.getOutputStream());
```
18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC505/EC505.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Idleness: Keep Screen On (addFlags)",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "20min"
},
"tags": [
"idleness",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.6",
"defaultSeverity": "Major"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
To avoid draining the battery, an Android device that is left idle quickly falls asleep.

Hence, keeping the screen on should be avoided, unless it is absolutely necessary. If so, developers typically use the `FLAG_KEEP_SCREEN_ON` in their activity. Another way to implement this is in their application's layout XML file, by using the `android:keepScreenOn` attribute.

## Noncompliant Code Example

```java
getWindow().addFlags(FLAG_KEEP_SCREEN_ON);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Score ecoCode: 2sur5

To avoid draining the battery, an iOS device that is left idle quickly falls asleep.

Hence, keeping the screen on should be avoided, unless it is absolutely necessary. If so, developers typically
disable the idle timer with `UIApplication.shared.isIdleTimerDisabled = true`.

## Noncompliant Code Example

```swift
UIApplication.shared.isIdleTimerDisabled = true
```

18 changes: 18 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC506/EC506.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Idleness: Keep Screen On (setFlags)",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "20min"
},
"tags": [
"idleness",
"environment",
"ecocode",
"android",
"eco-design"
],
"ecoScore": "0.6",
"defaultSeverity": "Major"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
To avoid draining the battery, an Android device that is left idle quickly falls asleep.

Hence, keeping the screen on should be avoided, unless it is absolutely necessary. If so, developers typically use the `FLAG_KEEP_SCREEN_ON` in their activity. Another way to implement this is in their application's layout XML file, by using the `android:keepScreenOn` attribute.

## Noncompliant Code Example

```java
getWindow().setFlags(FLAG_KEEP_SCREEN_ON, FLAG_KEEP_SCREEN_ON);
```
Loading