1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "wifi_system/supplicant_manager.h" 18 19 #include <android-base/logging.h> 20 #include <cutils/properties.h> 21 #include <fcntl.h> 22 #include <string.h> 23 #include <sys/stat.h> 24 #include <unistd.h> 25 26 // This ugliness is necessary to access internal implementation details 27 // of the property subsystem. 28 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 29 #include <sys/_system_properties.h> 30 31 namespace android { 32 namespace wifi_system { 33 namespace { 34 35 const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant"; 36 const char kSupplicantServiceName[] = "wpa_supplicant"; 37 38 } // namespace 39 40 bool SupplicantManager::StartSupplicant() { 41 char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; 42 int count = 200; /* wait at most 20 seconds for completion */ 43 const prop_info* pi; 44 unsigned serial = 0; 45 46 /* Check whether already running */ 47 if (property_get(kSupplicantInitProperty, supp_status, NULL) && 48 strcmp(supp_status, "running") == 0) { 49 return true; 50 } 51 52 /* 53 * Get a reference to the status property, so we can distinguish 54 * the case where it goes stopped => running => stopped (i.e., 55 * it start up, but fails right away) from the case in which 56 * it starts in the stopped state and never manages to start 57 * running at all. 58 */ 59 pi = __system_property_find(kSupplicantInitProperty); 60 if (pi != NULL) { 61 serial = __system_property_serial(pi); 62 } 63 64 property_set("ctl.start", kSupplicantServiceName); 65 sched_yield(); 66 67 while (count-- > 0) { 68 if (pi == NULL) { 69 pi = __system_property_find(kSupplicantInitProperty); 70 } 71 if (pi != NULL) { 72 /* 73 * property serial updated means that init process is scheduled 74 * after we sched_yield, further property status checking is based on this 75 */ 76 if (__system_property_serial(pi) != serial) { 77 __system_property_read(pi, NULL, supp_status); 78 if (strcmp(supp_status, "running") == 0) { 79 return true; 80 } else if (strcmp(supp_status, "stopped") == 0) { 81 return false; 82 } 83 } 84 } 85 usleep(100000); 86 } 87 return false; 88 } 89 90 bool SupplicantManager::StopSupplicant() { 91 char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; 92 int count = 200; /* wait at most 20 seconds for completion */ 93 94 /* Check whether supplicant already stopped */ 95 if (property_get(kSupplicantInitProperty, supp_status, NULL) && 96 strcmp(supp_status, "stopped") == 0) { 97 return true; 98 } 99 100 property_set("ctl.stop", kSupplicantServiceName); 101 sched_yield(); 102 103 while (count-- > 0) { 104 if (property_get(kSupplicantInitProperty, supp_status, NULL)) { 105 if (strcmp(supp_status, "stopped") == 0) return true; 106 } 107 usleep(100000); 108 } 109 LOG(ERROR) << "Failed to stop supplicant"; 110 return false; 111 } 112 113 bool SupplicantManager::IsSupplicantRunning() { 114 char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; 115 if (property_get(kSupplicantInitProperty, supp_status, NULL)) { 116 return strcmp(supp_status, "running") == 0; 117 } 118 return false; // Failed to read service status from init. 119 } 120 121 } // namespace wifi_system 122 } // namespace android 123