service: Teach autoconnect algorithm native mode

When network supports native auto connnect mode do not use the internal
auto connect algorithm for this network.

Introduce new CONNMAN_SERVICE_CONNECT_REASON_NATIVE and track the
service connection reason with it.
diff --git a/include/service.h b/include/service.h
index 4a129b4..8f6b36b 100644
--- a/include/service.h
+++ b/include/service.h
@@ -94,6 +94,7 @@
 	CONNMAN_SERVICE_CONNECT_REASON_AUTO	= 1,
 	CONNMAN_SERVICE_CONNECT_REASON_USER	= 2,
 	CONNMAN_SERVICE_CONNECT_REASON_SESSION	= 3,
+	CONNMAN_SERVICE_CONNECT_REASON_NATIVE	= 4,
 };
 
 struct connman_service;
diff --git a/src/service.c b/src/service.c
index 5bb7f12..a16350c 100644
--- a/src/service.c
+++ b/src/service.c
@@ -195,6 +195,8 @@
 		return "auto";
 	case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
 		return "session";
+	case CONNMAN_SERVICE_CONNECT_REASON_NATIVE:
+		return "native";
 	}
 
 	return "unknown";
@@ -3491,6 +3493,13 @@
 		return;
 
 	/*
+	 * Do not use the builtin auto connect, instead rely on the
+	 * native auto connect feature of the service.
+	 */
+	if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE)
+		return;
+
+	/*
 	 * Run service auto connect for other than VPN services. Afterwards
 	 * start also VPN auto connect process.
 	 */
@@ -4215,6 +4224,12 @@
 			continue;
 		}
 
+		if (service->connect_reason ==
+				CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
+			DBG("service %p uses native autonnect, skip", service);
+			continue;
+		}
+
 		if (service->pending ||
 				is_connecting(service->state) ||
 				is_connected(service->state)) {
@@ -6712,6 +6727,12 @@
 
 	__connman_service_clear_error(service);
 
+	if (__connman_network_native_autoconnect(service->network) &&
+			service->autoconnect) {
+		DBG("service %p switch connecting reason to native", service);
+		reason = CONNMAN_SERVICE_CONNECT_REASON_NATIVE;
+	}
+
 	err = service_connect(service);
 
 	DBG("service %p err %d", service, err);
@@ -7340,39 +7361,44 @@
 static void trigger_autoconnect(struct connman_service *service)
 {
 	struct connman_device *device;
+	bool native;
 
-	connman_network_set_autoconnect(service->network,
-				service->favorite && service->autoconnect);
-	if (service->favorite) {
-		device = connman_network_get_device(service->network);
-		if (device && !connman_device_get_scanning(device,
-						CONNMAN_SERVICE_TYPE_UNKNOWN)) {
+	if (!service->favorite)
+		return;
 
-			switch (service->type) {
-			case CONNMAN_SERVICE_TYPE_UNKNOWN:
-			case CONNMAN_SERVICE_TYPE_SYSTEM:
-			case CONNMAN_SERVICE_TYPE_P2P:
-				break;
+	native = __connman_network_native_autoconnect(service->network);
+	if (native && service->autoconnect) {
+		DBG("trigger native autoconnect");
+		connman_network_set_autoconnect(service->network, true);
+		return;
+	}
 
-			case CONNMAN_SERVICE_TYPE_GADGET:
-			case CONNMAN_SERVICE_TYPE_ETHERNET:
-				if (service->autoconnect) {
-					__connman_service_connect(service,
+	device = connman_network_get_device(service->network);
+	if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
+		return;
+
+	switch (service->type) {
+	case CONNMAN_SERVICE_TYPE_UNKNOWN:
+	case CONNMAN_SERVICE_TYPE_SYSTEM:
+	case CONNMAN_SERVICE_TYPE_P2P:
+		break;
+
+	case CONNMAN_SERVICE_TYPE_GADGET:
+	case CONNMAN_SERVICE_TYPE_ETHERNET:
+		if (service->autoconnect) {
+			__connman_service_connect(service,
 						CONNMAN_SERVICE_CONNECT_REASON_AUTO);
-					break;
-				}
-
-				/* fall through */
-			case CONNMAN_SERVICE_TYPE_BLUETOOTH:
-			case CONNMAN_SERVICE_TYPE_GPS:
-			case CONNMAN_SERVICE_TYPE_VPN:
-			case CONNMAN_SERVICE_TYPE_WIFI:
-			case CONNMAN_SERVICE_TYPE_CELLULAR:
-				do_auto_connect(service,
-					CONNMAN_SERVICE_CONNECT_REASON_AUTO);
-				break;
-			}
+			break;
 		}
+
+		/* fall through */
+	case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+	case CONNMAN_SERVICE_TYPE_GPS:
+	case CONNMAN_SERVICE_TYPE_VPN:
+	case CONNMAN_SERVICE_TYPE_WIFI:
+	case CONNMAN_SERVICE_TYPE_CELLULAR:
+		do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+		break;
 	}
 }