1 /****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #include "AlarmTestHarness.h" 20 21 #include <fcntl.h> 22 #include <sys/mman.h> 23 #include <unistd.h> 24 25 #include <hardware/bluetooth.h> 26 27 extern "C" { 28 #include "osi/include/alarm.h" 29 #include "osi/include/allocation_tracker.h" 30 #include "osi/include/wakelock.h" 31 } 32 33 static timer_t timer; 34 static alarm_cb saved_callback; 35 static void *saved_data; 36 static AlarmTestHarness *current_harness; 37 38 static void timer_callback(void *) { 39 saved_callback(saved_data); 40 } 41 42 void AlarmTestHarness::SetUp() { 43 AllocationTestHarness::SetUp(); 44 45 current_harness = this; 46 TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 100; 47 48 struct sigevent sigevent; 49 memset(&sigevent, 0, sizeof(sigevent)); 50 sigevent.sigev_notify = SIGEV_THREAD; 51 sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback; 52 sigevent.sigev_value.sival_ptr = NULL; 53 timer_create(CLOCK_BOOTTIME, &sigevent, &timer); 54 55 // TODO (jamuraa): maybe use base::CreateNewTempDirectory instead? 56 #if defined(OS_GENERIC) 57 tmp_dir_ = "/tmp/btwlXXXXXX"; 58 #else // !defined(OS_GENERIC) 59 tmp_dir_ = "/data/local/tmp/btwlXXXXXX"; 60 #endif // !defined(OS_GENERIC) 61 62 char *buffer = const_cast<char *>(tmp_dir_.c_str()); 63 char *dtemp = mkdtemp(buffer); 64 if (!dtemp) { 65 perror("Can't make wake lock test directory: "); 66 assert(false); 67 } 68 69 lock_path_ = tmp_dir_ + "/wake_lock"; 70 unlock_path_ = tmp_dir_ + "/wake_unlock"; 71 72 creat(lock_path_.c_str(), S_IRWXU); 73 creat(unlock_path_.c_str(), S_IRWXU); 74 75 wakelock_set_paths(lock_path_.c_str(), unlock_path_.c_str()); 76 } 77 78 void AlarmTestHarness::TearDown() { 79 alarm_cleanup(); 80 wakelock_cleanup(); 81 82 // clean up the temp wake lock directory 83 unlink(lock_path_.c_str()); 84 unlink(unlock_path_.c_str()); 85 rmdir(tmp_dir_.c_str()); 86 87 timer_delete(timer); 88 AllocationTestHarness::TearDown(); 89 } 90 91 92 bool AlarmTestHarness::WakeLockHeld() { 93 bool held = false; 94 95 int lock_fd = open(lock_path_.c_str(), O_RDONLY); 96 assert(lock_fd >= 0); 97 98 int unlock_fd = open(unlock_path_.c_str(), O_RDONLY); 99 assert(unlock_fd >= 0); 100 101 struct stat lock_stat, unlock_stat; 102 fstat(lock_fd, &lock_stat); 103 fstat(unlock_fd, &unlock_stat); 104 105 assert(lock_stat.st_size >= unlock_stat.st_size); 106 107 void *lock_file = mmap(nullptr, lock_stat.st_size, PROT_READ, 108 MAP_PRIVATE, lock_fd, 0); 109 110 void *unlock_file = mmap(nullptr, unlock_stat.st_size, PROT_READ, 111 MAP_PRIVATE, unlock_fd, 0); 112 113 if (memcmp(lock_file, unlock_file, unlock_stat.st_size) == 0) { 114 held = lock_stat.st_size > unlock_stat.st_size; 115 } else { 116 // these files should always either be with a lock that has more, 117 // or equal. 118 assert(false); 119 } 120 121 munmap(lock_file, lock_stat.st_size); 122 munmap(unlock_file, unlock_stat.st_size); 123 close(lock_fd); 124 close(unlock_fd); 125 126 return held; 127 } 128