5 // Created by Mitch Adler on 11/2/16.
9 #import <Foundation/Foundation.h>
11 #import "CKDAKSLockMonitor.h"
13 #include <utilities/SecCFRelease.h>
14 #include <utilities/SecAKSWrappers.h>
15 #include <utilities/debugging.h>
18 @interface CKDAKSLockMonitor ()
20 @property XPCNotificationDispatcher* dispatcher;
21 @property XPCNotificationBlock notificationBlock;
25 @implementation CKDAKSLockMonitor
27 + (instancetype) monitor {
28 return [[CKDAKSLockMonitor alloc] init];
31 - (instancetype)init {
35 XPCNotificationDispatcher* dispatcher = [XPCNotificationDispatcher dispatcher];
37 [dispatcher addListener: self];
40 self->_unlockedSinceBoot = false;
48 - (void) handleNotification:(const char *)name {
49 if (strcmp(name, kUserKeybagStateChangeNotification) == 0) {
54 - (void) notifyListener {
57 [self.listener locked];
59 [self.listener unlocked];
64 - (void)connectTo: (NSObject<CKDLockListener>*) listener {
65 self->_listener = listener;
66 [self notifyListener];
70 CFErrorRef aksError = NULL;
71 bool locked = true; // Assume locked if we get an error
73 if (!SecAKSGetIsLocked(&locked, &aksError)) {
74 secerror("%@ Got error querying lock state: %@", self, aksError);
75 CFReleaseSafe(aksError);
78 BOOL previousLocked = self.locked;
79 self->_locked = locked;
82 self->_unlockedSinceBoot = true;
85 if (previousLocked != self.locked) {
86 // recheck might get called from ckdkvsproxy_queue (see 30510390)
87 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
88 [self notifyListener];