**Agent ID:** SA-016 **Binary:** `./analysis/facebook/345.0/Facebook.app/Frameworks/FBSharedFramework.framework/FBSharedFramework` **Analysis Date:** 2025-12-30 **Status:** Complete
Executive Summary
This analysis documents Facebook's Stories/Snacks tray visibility control system. The investigation reveals a sophisticated system for controlling when the stories tray is visible and how bucket reranking occurs based on visibility state. Key findings include:
- undefined
1. Tray Visibility Method Addresses
Primary Methods Located
| Address | Class | Method | Description |
|---|---|---|---|
| 0x000da4b8 | FBSnacksTrayDeliveryLifecycleTNLHandler | trayVisibilityChangedWithTrayLogInfo:visible: | Main visibility change handler |
| 0x000a94cc | FBSnacksUnifiedQueryController | _setIsTrayVisible: | Internal tray visibility setter |
| 0x00164e4c | FBSnacksTrayActivityTracker | setIsTrayVisible: | Public tray visibility setter |
| 0x0002651c | FBSnacksTrayActivityTracker | isTrayVisible | Visibility getter |
| 0x000da32c | FBSnacksTrayActivityTracker | trayVisibilityChanged: | Visibility change notification |
| 0x001e88b4 | FBSnacksCSRRerankManager | reRankBucketsWithTrayVisibility:viewerIsPresenting:currentTime: | Rerank with visibility |
Reranking-Related Methods
| Address | Class | Method |
|---|---|---|
| 0x000da3ac | Multiple | reRankBucketsWithTrayActivityTrigger: |
| 0x00516e14 | Multiple | reRankBucketsWithDeltaUpdateTrigger |
| 0x000da38c | Multiple | changeTrayVisibilityConditionForReranking: |
| 0x0066cc24 | Multiple | reRankBucketsUnconditionally |
| 0x002c4498 | FBSnacksCSRUnifiedRerankManager | _reRankBucketsWithTrigger:currentTime: |
2. Decompilation Results
2.1 _setIsTrayVisible: (FBSnacksUnifiedQueryController @ 0x000a94cc)
method.FBSnacksUnifiedQueryController._setIsTrayVisible:
; Store visibility flag at offset 0x15a from self
strb w2, [x0, 0x15a] ; arg3 = visible (bool)
; Compare visibility to 0
cmp w2, 0
; Load either 0x1a0 or 0x198 based on visibility
mov w8, 0x1a0 ; offset when hidden
mov w9, 0x198 ; offset when visible
csel x8, x9, x8, ne ; select based on visibility
; Increment counter at selected offset
ldr x9, [x0, x8]
add x9, x9, 1
str x9, [x0, x8]
ret
**Analysis:** This method:
- undefined
2.2 trayVisibilityChangedWithTrayLogInfo:visible: (FBSnacksTrayDeliveryLifecycleTNLHandler @ 0x000da4b8)
method.FBSnacksTrayDeliveryLifecycleTNLHandler.trayVisibilityChangedWithTrayLogInfo:visible:
; Early return if bit 0 of w4 (visible arg) is zero
tbz w4, 0, 0xda4c0 ; if (visible == false) goto 0xda4c0
ret ; early return if visible is false
0xda4c0:
stp x29, x30, [sp, -0x10]!
bl fcn.00007e3c ; likely objc_retainAutoreleasedReturnValue
mov x19, x0
bl fcn.000a6b48 ; internal processing
bl fcn.000da500 ; additional processing
; Load address of constant string
adrp x3, 0x13b3000
add x3, x3, 0x250 ; likely logging tag
mov x2, x20
bl QPLMarkerAnnotateSyncOnSession ; Performance logging
bl fcn.000da51c
bl fcn.00013cbc
ldr w1, [x21, 0x9c] ; load parameter
ldrsh w3, [x8, 0x414] ; load additional parameter
mov x2, x20
bl fcn.000116e0
b QPLMarkerEndOnSession ; End performance marker
**Analysis:** This method:
- undefined
2.3 trayVisibilityChanged: (FBSnacksTrayActivityTracker @ 0x000da32c)
method.FBSnacksTrayActivityTracker.trayVisibilityChanged:
stp x29, x30, [sp, -0x10]!
bl fcn.00007e3c ; objc_retainAutoreleasedReturnValue
mov x19, x0
strb w2, [x0, 0x18] ; Store visibility at offset 0x18
add x20, x0, 0x10
bl fcn.0006cd7c ; Process change
mov x21, x0
ldrb w2, [x19, 0x18] ; Reload visibility
bl fcn.012e5fa4 ; Notify observers
**Analysis:** This method:
- undefined
2.4 reRankBucketsWithTrayVisibility:viewerIsPresenting:currentTime: (FBSnacksCSRRerankManager @ 0x001e88b4)
method.FBSnacksCSRRerankManager.reRankBucketsWithTrayVisibility:viewerIsPresenting:currentTime:
stp x29, x30, [sp, -0x10]!
bl fcn.00007c58 ; Setup
mov x21, x4 ; currentTime parameter
mov x22, x3 ; viewerIsPresenting parameter
mov x23, x2 ; trayVisibility parameter
mov x20, x0 ; self
bl fcn.00030ba4 ; Process rerank
bl fcn.000764e8 ; Additional processing
bl fcn.012e5fa4 ; Notify
**Analysis:** This method takes three parameters:
- undefined
3. Class Ownership
FBSnacksTrayActivityTracker (Class 9540)
**Location:** 0x01c8b7a8 **Base Class:** NSObject **Size:** 4489612 bytes
**Instance Variables:**
| Offset | Name | Purpose |
|---|---|---|
| 0x01bda678 | _session | Session reference |
| 0x01bda67c | _rerankHandler | Handler for reranking |
| 0x01bda680 | _isTrayVisible | Current visibility state |
| 0x01bda684 | _isViewerPresenting | Viewer presentation state |
| 0x01bda688 | _isTrayScrolledToStartingPosition | Scroll state |
**Key Methods:**
- undefined
FBSnacksCSRRerankManager (Class 1439)
**Location:** 0x01bed418 **Base Class:** NSObject **Size:** 3985148 bytes
**Instance Variables:**
| Offset | Name | Purpose |
|---|---|---|
| 0x01bbfd9c | _csrConnectionManager | Connection manager |
| 0x01bbfda0 | _session | Session reference |
| 0x01bbfda4 | _reRankBucketsWhenTrayIsNotVisible | **KEY FLAG** - controls hidden reranking |
| 0x01bbfda8 | _rerankRateLimitSec | Rate limiting |
| 0x01bbfdac | _lastRerankDate | Last rerank timestamp |
| 0x01bbfdb0 | _isTrayVisible | Visibility state mirror |
| 0x01bbfdb4 | _isViewerPresenting | Viewer state |
FBSnacksUnifiedQueryController (Class 1297)
**Location:** 0x01bea7b8 **Base Class:** NSObject **Size:** 16496136 bytes
Contains the internal `_setIsTrayVisible:` implementation with visibility counters.
FBSnacksTrayDeliveryLifecycleTNLHandler (Class 3414)
**Location:** 0x01c13d48 **Base Class:** NSObject **Size:** 17518036 bytes
Handles the delivery lifecycle including visibility change events with QPL logging.
4. Privacy Indicator System
privacyIndicatorUnit Property
Found in multiple classes:
| Class | Method Address |
|---|---|
| FBFeedSecondaryActionButtonTapComponent | 0x00c3b06c |
| FBFeedSecondaryActionButtonTapComponentController | 0x0002bb70 |
**String Reference:** `story_viewer_privacy_indicator` at 0x01eeb2d2
The `privacyIndicatorUnit` is stored as:
- undefined
This appears to be used for displaying privacy indicators in the stories viewer, potentially related to who can see a story.
5. Status Bar Suppression
shouldHideStatusBar Property
Found in multiple classes related to stories/snacks:
| Class | Get Method | Set Method | Ivar Offset |
|---|---|---|---|
| FBSnacksSettingsIntentTarget | 0x000237e8 | - | 0x01bd4c7c |
| Unknown (offset 0x01bbf390) | 0x009957e8 | 0x0099214c | 0x01bbf390 |
| Unknown (offset 0x01bbf45c) | 0x009f6ba4 | 0x009f65c0 | 0x01bbf45c |
Status Bar Control Methods
initWithSession:entrypoint:source:shouldHideStatusBar:shouldHideXpostingToIGSetting:dismissWithConfirmedBlock:threadFragment:trayBucketFragment:
initWithSession:withProfilePicUrl:threadFragment:bucketFragment:shouldHideStatusBar:shouldUseMembersOnlyAsDefaultPrivacyModel:
These initializers show that status bar hiding is a configurable option passed when creating stories viewer controllers.
6. iOS Version Checking
Version Check Patterns Found
The binary references standard iOS version checking:
- undefined
**No explicit iOS 14 version check was found** in string form. The iOS 14+ orange dot indicator (introduced for camera/microphone access) would be handled at the system level, not by the app directly.
7. Complete Visibility Suppression Chain
User Action (scroll, tap, etc.)
|
v
FBSnacksTrayActivityTracker
|- setIsTrayVisible: (0x00164e4c)
| Stores visibility at offset 0x18
|
|- trayVisibilityChanged: (0x000da32c)
|
v
FBSnacksUnifiedQueryController
|- _setIsTrayVisible: (0x000a94cc)
Stores at offset 0x15a
Increments counter at 0x198 (visible) or 0x1a0 (hidden)
|
v
FBSnacksTrayDeliveryLifecycleTNLHandler
|- trayVisibilityChangedWithTrayLogInfo:visible: (0x000da4b8)
Logs via QPL system
Early return if becoming visible
Full processing if becoming hidden
|
v
FBSnacksCSRRerankManager
|- changeTrayVisibilityConditionForReranking: (0x000da38c)
|
|- IF _reRankBucketsWhenTrayIsNotVisible == true:
| |- reRankBucketsWithTrayVisibility:viewerIsPresenting:currentTime: (0x001e88b4)
|
v
Bucket reranking occurs (or not, based on flag)
8. Key Configuration Points
_reRankBucketsWhenTrayIsNotVisible (Offset 0x01bbfda4)
This boolean flag in FBSnacksCSRRerankManager controls whether story buckets are reranked when the tray is not visible. This is significant because:
- undefined
This flag could be used to:
- undefined
Visibility Change Counting
The counting mechanism in `_setIsTrayVisible:` tracks:
- undefined
This data is likely used for:
- undefined
9. Related Configuration Strings
| String | Purpose |
|---|---|
| story_viewer_privacy_indicator | Privacy indicator config key |
| shouldHideStatusBar | Status bar suppression flag |
| should_hide_nav_bar | Navigation bar suppression |
| should_hide_title | Title suppression |
| should_hide_unit_nav | Unit navigation suppression |
10. Conclusions
- undefined
Appendix: Method Signatures
// FBSnacksTrayActivityTracker
- (void)trayVisibilityChanged:(BOOL)visible;
- (BOOL)isTrayVisible;
- (void)setIsTrayVisible:(BOOL)visible;
- (void)viewerWillAppear;
- (void)viewerDidDisappear;
// FBSnacksUnifiedQueryController
- (void)_setIsTrayVisible:(BOOL)visible;
// FBSnacksTrayDeliveryLifecycleTNLHandler
- (void)trayVisibilityChangedWithTrayLogInfo:(id)logInfo visible:(BOOL)visible;
// FBSnacksCSRRerankManager
- (void)changeTrayVisibilityConditionForReranking:(BOOL)visible;
- (void)reRankBucketsWithTrayVisibility:(BOOL)visible
viewerIsPresenting:(BOOL)presenting
currentTime:(NSTimeInterval)time;