Skip to content

Commit 6e4d5fe

Browse files
author
David Gräff
committed
Fix crashes of concurrent access
Fix hide/unhide bug Fix update outlet bug Replace hash comparison with simple hasChanged boolean.
1 parent 6eb0b24 commit 6e4d5fe

32 files changed

+959
-1277
lines changed

.idea/workspace.xml

Lines changed: 320 additions & 594 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/app.iml

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
<component name="FacetManager">
44
<facet type="android" name="Android">
55
<configuration>
6-
<option name="SELECTED_BUILD_VARIANT" value="release" />
7-
<option name="ASSEMBLE_TASK_NAME" value="assembleRelease" />
8-
<option name="COMPILE_JAVA_TASK_NAME" value="compileReleaseJava" />
9-
<option name="SOURCE_GEN_TASK_NAME" value="generateReleaseSources" />
6+
<option name="SELECTED_BUILD_VARIANT" value="debug" />
7+
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
8+
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugJava" />
9+
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
10+
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
1011
<option name="ALLOW_USER_CONFIGURATION" value="false" />
1112
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
1213
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@@ -21,21 +22,26 @@
2122
</facet>
2223
</component>
2324
<component name="NewModuleRootManager" inherit-compiler-output="false">
24-
<output url="file://$MODULE_DIR$/build/classes/release" />
25+
<output url="file://$MODULE_DIR$/build/classes/debug" />
2526
<exclude-output />
2627
<content url="file://$MODULE_DIR$">
27-
<sourceFolder url="file://$MODULE_DIR$/build/source/r/release" isTestSource="false" generated="true" />
28-
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/release" isTestSource="false" generated="true" />
29-
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/release" isTestSource="false" generated="true" />
30-
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/release" isTestSource="false" generated="true" />
31-
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/release" type="java-resource" />
32-
<sourceFolder url="file://$MODULE_DIR$/src/release/res" type="java-resource" />
33-
<sourceFolder url="file://$MODULE_DIR$/src/release/resources" type="java-resource" />
34-
<sourceFolder url="file://$MODULE_DIR$/src/release/aidl" isTestSource="false" />
35-
<sourceFolder url="file://$MODULE_DIR$/src/release/assets" isTestSource="false" />
36-
<sourceFolder url="file://$MODULE_DIR$/src/release/java" isTestSource="false" />
37-
<sourceFolder url="file://$MODULE_DIR$/src/release/jni" isTestSource="false" />
38-
<sourceFolder url="file://$MODULE_DIR$/src/release/rs" isTestSource="false" />
28+
<sourceFolder url="file://$MODULE_DIR$/build/source/r/debug" isTestSource="false" generated="true" />
29+
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" generated="true" />
30+
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" generated="true" />
31+
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" generated="true" />
32+
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" type="java-resource" />
33+
<sourceFolder url="file://$MODULE_DIR$/build/source/r/test/debug" isTestSource="true" generated="true" />
34+
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test/debug" isTestSource="true" generated="true" />
35+
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test/debug" isTestSource="true" generated="true" />
36+
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/test/debug" isTestSource="true" generated="true" />
37+
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/test/debug" type="java-test-resource" />
38+
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
39+
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
40+
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
41+
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" />
42+
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
43+
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
44+
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
3945
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
4046
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
4147
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />

app/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ android {
1212
buildTypes {
1313
release {
1414
zipAlign true
15-
runProguard false
15+
runProguard true
16+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
1617
debuggable false
1718
}
1819
}

app/src/main/aidl/oly/netpowerctrl/plugins/INetPwrCtrlPluginResult.aidl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ interface INetPwrCtrlPluginResult {
77
void intValue(int id, String name, int min, int max, int value);
88
void booleanValue(int id, String name, boolean value);
99
void action(int id, int groupID, String name);
10-
void header(String name);
1110
void finished();
1211

1312
}

app/src/main/java/oly/netpowerctrl/anel/AnelBroadcastSendJob.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import java.net.InterfaceAddress;
88
import java.net.NetworkInterface;
99
import java.net.SocketException;
10-
import java.util.ArrayList;
1110
import java.util.Enumeration;
11+
import java.util.List;
1212
import java.util.Set;
1313

1414
import oly.netpowerctrl.application_state.NetpowerctrlApplication;
@@ -74,7 +74,7 @@ public void process(DeviceSend deviceSend) {
7474
// Toast.LENGTH_SHORT).show();
7575

7676
// Query all existing anel devices directly
77-
ArrayList<DeviceInfo> devices = NetpowerctrlApplication.getDataController().configuredDevices;
77+
List<DeviceInfo> devices = NetpowerctrlApplication.getDataController().configuredDevices;
7878
for (DeviceInfo di : devices) {
7979
if (di.pluginID.equals(AnelPlugin.PLUGIN_ID))
8080
di.getPluginInterface().requestData(di);

app/src/main/java/oly/netpowerctrl/anel/AnelDeviceDiscoveryThread.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private DeviceInfo createReceivedAnelDevice(String DeviceName, String HostName,
7474

7575
di.SendPort = SharedPrefs.getDefaultSendPort();
7676
di.setReachable();
77-
di.updated = System.currentTimeMillis();
77+
di.setUpdatedNow();
7878
return di;
7979
}
8080

@@ -127,10 +127,10 @@ public void run() {
127127
oi.id = (i - 16 + 1) + 10; // 1-based, and for IO we add 10. range: 11..19
128128
oi.setDescription(io_port[0]);
129129
oi.current_value = io_port[2].equals("1") ? DevicePort.ON : DevicePort.OFF;
130-
di.DevicePorts.add(oi);
130+
di.add(oi);
131131
}
132132
di.Temperature = msg[24];
133-
di.FirmwareVersion = msg[25].trim();
133+
di.Version = msg[25].trim();
134134
}
135135

136136
}
@@ -151,7 +151,7 @@ else if (msg.length < 14) {
151151
oi.current_value = outlet[1].equals("1") ? DevicePort.ON : DevicePort.OFF;
152152
oi.Disabled = (disabledOutlets & (1 << i)) != 0;
153153

154-
di.DevicePorts.add(oi);
154+
di.add(oi);
155155
}
156156

157157
new Handler(NetpowerctrlApplication.instance.getMainLooper()).post(new Runnable() {

app/src/main/java/oly/netpowerctrl/anel/AnelPlugin.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package oly.netpowerctrl.anel;
22

3+
import android.content.Context;
4+
import android.content.Intent;
5+
import android.net.Uri;
36
import android.os.Handler;
47
import android.os.Looper;
58
import android.util.Base64;
@@ -11,6 +14,7 @@
1114
import java.net.URL;
1215
import java.net.URLEncoder;
1316
import java.util.ArrayList;
17+
import java.util.Iterator;
1418
import java.util.List;
1519
import java.util.Locale;
1620
import java.util.Set;
@@ -127,17 +131,20 @@ private static void executeDeviceBatch(DeviceInfo di, List<Scene.PortAndCommand>
127131
boolean containsIO = false;
128132

129133
// First step: Setup data byte (outlet, io) to reflect the current state of the device ports.
130-
for (int i = 0; i < di.DevicePorts.size(); ++i) {
131-
if (di.DevicePorts.get(i).Disabled || di.DevicePorts.get(i).current_value == 0)
134+
di.lockDevicePorts();
135+
Iterator<DevicePort> it = di.getDevicePortIterator();
136+
while (it.hasNext()) {
137+
DevicePort oi = it.next();
138+
if (oi.Disabled || oi.current_value == 0)
132139
continue;
133-
134-
int id = (int) di.DevicePorts.get(i).id;
140+
int id = (int) oi.id;
135141
if (id >= 10) {
136142
data_io = switchOn(data_io, id - 10);
137143
} else {
138144
data_outlet = switchOn(data_outlet, id);
139145
}
140146
}
147+
di.releaseDevicePorts();
141148

142149
// Second step: Apply commands
143150
for (Scene.PortAndCommand c : command_list) {
@@ -183,13 +190,13 @@ private static void executeDeviceBatch(DeviceInfo di, List<Scene.PortAndCommand>
183190
data[0] = 'S';
184191
data[1] = 'w';
185192
data[2] = data_outlet;
186-
DeviceSend.instance().addJob(new DeviceSend.SendJob(di, data, DeviceSend.INQUERY_REQUEST, true));
193+
DeviceSend.instance().addJob(new DeviceSend.SendJob(di, data, DeviceSend.INQUERY_REQUEST));
187194
}
188195
if (containsIO) {
189196
data[0] = 'I';
190197
data[1] = 'O';
191198
data[2] = data_io;
192-
DeviceSend.instance().addJob(new DeviceSend.SendJob(di, data, DeviceSend.INQUERY_REQUEST, true));
199+
DeviceSend.instance().addJob(new DeviceSend.SendJob(di, data, DeviceSend.INQUERY_REQUEST));
193200
}
194201

195202
if (callback != null)
@@ -224,7 +231,7 @@ else if (command == DevicePort.TOGGLE)
224231
port.id, port.device.UserName, port.device.Password).getBytes();
225232
}
226233

227-
DeviceSend.instance().addJob(new DeviceSend.SendJob(port.device, data, DeviceSend.INQUERY_REQUEST, true));
234+
DeviceSend.instance().addJob(new DeviceSend.SendJob(port.device, data, DeviceSend.INQUERY_REQUEST));
228235

229236
if (callback != null)
230237
callback.onExecutionFinished(1);
@@ -244,7 +251,7 @@ public void requestData() {
244251

245252
@Override
246253
public void requestData(DeviceInfo di) {
247-
DeviceSend.instance().addJob(new DeviceSend.SendJob(di, "wer da?\r\n".getBytes(), DeviceSend.INQUERY_REQUEST, true));
254+
DeviceSend.instance().addJob(new DeviceSend.SendJob(di, "wer da?\r\n".getBytes(), DeviceSend.INQUERY_REQUEST));
248255
}
249256

250257
@Override
@@ -349,6 +356,13 @@ public void prepareForDevices(DeviceInfo device) {
349356
startDiscoveryThreads((device != null) ? device.ReceivePort : 0);
350357
}
351358

359+
@Override
360+
public void openConfigurationPage(DeviceInfo device, Context context) {
361+
Intent browse = new Intent(Intent.ACTION_VIEW,
362+
Uri.parse("http://" + device.HostName + ":" + Integer.valueOf(device.HttpPort).toString()));
363+
context.startActivity(browse);
364+
}
365+
352366
//
353367
// public boolean onlyLinkLocalDevices() {
354368
// boolean linkLocals = true;

app/src/main/java/oly/netpowerctrl/anel/ConfigureDeviceFragment.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import oly.netpowerctrl.application_state.NetpowerctrlApplication;
2020
import oly.netpowerctrl.application_state.PluginInterface;
2121
import oly.netpowerctrl.datastructure.DeviceInfo;
22+
import oly.netpowerctrl.datastructure.DevicePort;
2223
import oly.netpowerctrl.network.DeviceQuery;
2324
import oly.netpowerctrl.network.DeviceQueryResult;
2425
import oly.netpowerctrl.network.DeviceUpdate;
@@ -211,7 +212,9 @@ public void onDeviceUpdated(DeviceInfo di, boolean willBeRemoved) {
211212
if (deviceQuery != null) {
212213
deviceQuery.addDevice(device, false);
213214
}
214-
pi.execute(device.DevicePorts.get(0), device.DevicePorts.get(0).current_value, null);
215+
DevicePort oi = device.getFirst();
216+
if (oi != null)
217+
pi.execute(oi, oi.current_value, null);
215218
Handler handler = new Handler();
216219
// Timeout is 1,1s
217220
handler.postDelayed(new Runnable() {
@@ -242,7 +245,7 @@ public void onDeviceQueryFinished(List<DeviceInfo> timeout_devices) {
242245
@Override
243246
public void onDeviceError(DeviceInfo di, String error_message) {
244247
if (test_state == TestStates.TEST_ACCESS) {
245-
if (di.equals(device)) {
248+
if (di.equalsByUniqueID(device)) {
246249
test_state = TestStates.TEST_INIT;
247250
}
248251
}

app/src/main/java/oly/netpowerctrl/application_state/NetpowerctrlApplication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ public void run() {
166166
}, 1000);
167167

168168
// First try a broadcast
169+
NetpowerctrlApplication.getDataController().clearNewDevices();
169170
new DeviceQuery(new DeviceQueryResult() {
170171
@Override
171172
public void onDeviceTimeout(DeviceInfo di) {
172-
di.updated = System.currentTimeMillis();
173173
}
174174

175175
@Override

app/src/main/java/oly/netpowerctrl/application_state/NetpowerctrlService.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void onReceive(Context context, Intent intent) {
5656

5757
List<DeviceInfo> devices = NetpowerctrlApplication.getDataController().configuredDevices;
5858
for (DeviceInfo di : devices) {
59-
di.updated = 0;
59+
di.setUpdatedNever();
6060
}
6161

6262
if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected())
@@ -148,14 +148,7 @@ public void start() {
148148
}
149149
NetpowerctrlApplication.instance.detectNewDevicesAndReachability(null);
150150

151-
if (!SharedPrefs.getLoadExtensions())
152-
return;
153151

154-
if (!isBroadcastListener) {
155-
isBroadcastListener = true;
156-
NetpowerctrlApplication.instance.registerReceiver(pluginBroadcastListener,
157-
new IntentFilter(PLUGIN_RESPONSE_ACTION));
158-
}
159152
}
160153

161154
private void createRemotePlugin(String serviceName,
@@ -183,6 +176,12 @@ private void discover() {
183176
if (!SharedPrefs.getLoadExtensions())
184177
return;
185178

179+
if (!isBroadcastListener) {
180+
isBroadcastListener = true;
181+
NetpowerctrlApplication.instance.registerReceiver(pluginBroadcastListener,
182+
new IntentFilter(PLUGIN_RESPONSE_ACTION));
183+
}
184+
186185
Intent i = new Intent(PLUGIN_QUERY_ACTION);
187186
i.putExtra(PAYLOAD_SERVICENAME, NetpowerctrlActivity.class.getCanonicalName());
188187
NetpowerctrlApplication.instance.sendBroadcast(i);

0 commit comments

Comments
 (0)