// // SCBlackCameraPreviewDetector.m // Snapchat // // Created by Derek Wang on 25/01/2018. // #import "SCBlackCameraPreviewDetector.h" #import "SCBlackCameraReporter.h" #import "SCMetalUtils.h" #import #import #import #import // Check whether preview is visible when AVCaptureSession is running static CGFloat const kSCBlackCameraCheckingDelay = 0.5; @interface SCBlackCameraPreviewDetector () { BOOL _previewVisible; dispatch_block_t _checkingBlock; } @property (nonatomic) SCQueuePerformer *queuePerformer; @property (nonatomic) SCBlackCameraReporter *reporter; @end @implementation SCBlackCameraPreviewDetector - (instancetype)initWithPerformer:(SCQueuePerformer *)performer reporter:(SCBlackCameraReporter *)reporter { self = [super init]; if (self) { _queuePerformer = performer; _reporter = reporter; } return self; } - (void)capturePreviewDidBecomeVisible:(BOOL)visible { [_queuePerformer perform:^{ _previewVisible = visible; }]; } - (void)sessionDidChangeIsRunning:(BOOL)running { if (running) { [self _scheduleCheck]; } else { [_queuePerformer perform:^{ if (_checkingBlock) { dispatch_block_cancel(_checkingBlock); _checkingBlock = nil; } }]; } } - (void)_scheduleCheck { [_queuePerformer perform:^{ @weakify(self); _checkingBlock = dispatch_block_create(0, ^{ @strongify(self); SC_GUARD_ELSE_RETURN(self); self->_checkingBlock = nil; [self _checkPreviewState]; }); [_queuePerformer perform:_checkingBlock after:kSCBlackCameraCheckingDelay]; }]; } - (void)_checkPreviewState { if (!_previewVisible) { runOnMainThreadAsynchronously(^{ // Make sure the app is in foreground SC_GUARD_ELSE_RETURN([UIApplication sharedApplication].applicationState == UIApplicationStateActive); SCBlackCameraCause cause = SCDeviceSupportsMetal() ? SCBlackCameraRenderingPaused : SCBlackCameraPreviewIsHidden; [_reporter reportBlackCameraWithCause:cause]; [_reporter fileShakeTicketWithCause:cause]; }); } } @end