# ePhone mobile — dependencies & native setup (Step 3)

## npm packages
```bash
npm i jssip react-native-webrtc react-native-callkeep \
      react-native-incall-manager \
      @react-native-firebase/app @react-native-firebase/messaging \
      react-native-voip-push-notification \
      @react-native-async-storage/async-storage
```

## Why each one
| Package | Role |
|---|---|
| `jssip` | SIP signalling over WSS (REGISTER, INVITE, session state) |
| `react-native-webrtc` | RTCPeerConnection + DTLS-SRTP media; provides the WebRTC globals jssip needs (`registerGlobals()`) |
| `react-native-callkeep` | Native CallKit (iOS) / ConnectionService (Android) lock-screen UI |
| `react-native-incall-manager` | Speaker/earpiece routing, proximity sensor, audio session |
| `@react-native-firebase/messaging` | FCM high-priority data push (Android wake) |
| `react-native-voip-push-notification` | Apple PushKit VoIP push (iOS wake) |

## iOS native setup
- **Capabilities**: Push Notifications, Background Modes → *Voice over IP*, *Audio*, *Background fetch*, *Remote notifications*.
- **PushKit**: create a VoIP Services certificate **or** a `.p8` token key; APNs topic = `<bundle-id>.voip`.
- **CallKit** is enabled automatically by react-native-callkeep; no extra entitlement.
- Add `NSMicrophoneUsageDescription` to `Info.plist`.
- iOS 13+: you MUST report the incoming call to CallKit in the same PushKit
  handler tick (handled in `PushService.initIOS`) or the OS kills the app.

## Android native setup
- `AndroidManifest.xml`: `RECORD_AUDIO`, `INTERNET`, `FOREGROUND_SERVICE`,
  `FOREGROUND_SERVICE_MICROPHONE` (API 34+), `POST_NOTIFICATIONS` (API 33+),
  `USE_FULL_SCREEN_INTENT` (lock-screen ring on API 34+).
- Register the CallKeep `ConnectionService` + `RNCallKeepBackgroundMessagingService`
  per the react-native-callkeep README.
- `google-services.json` from Firebase console for FCM.
- Battery optimisation: prompt the engineer to exempt ePhone, or pushes are
  throttled when the phone dozes.

## Data flow recap
```
OUTBOUND:  Dialpad -> callManager.startOutgoing() -> sipEngine.placeCall()
           -> WSS INVITE -> Asterisk [from-mobile] -> trunk2 -> PSTN

INBOUND:   PSTN -> trunk2 -> [from-trunk] -> [ring-engineer]
           -> ephone-push.sh (APNs/FCM) -> phone wakes
           -> PushService.wakeAndRegister() -> REGISTER
           -> Asterisk INVITE -> sipEngine 'incoming'
           -> CallKeep native ring -> engineer answers
```
