1 package com.android.tv.mdnsoffloadmanager; 2 3 import android.util.Log; 4 5 import androidx.annotation.NonNull; 6 import androidx.annotation.WorkerThread; 7 8 import java.io.PrintWriter; 9 import java.util.Collection; 10 import java.util.Collections; 11 import java.util.HashSet; 12 import java.util.List; 13 import java.util.Set; 14 15 @WorkerThread 16 public class InterfaceOffloadManager { 17 18 private static final String TAG = InterfaceOffloadManager.class.getSimpleName(); 19 20 private final String mNetworkInterface; 21 private final OffloadIntentStore mOffloadIntentStore; 22 private final OffloadWriter mOffloadWriter; 23 private final Set<Integer> mCurrentOffloadKeys = new HashSet<>(); 24 private final Set<String> mCurrentPassthroughQNames = new HashSet<>(); 25 private boolean mIsNetworkAvailable = false; 26 InterfaceOffloadManager( @onNull String networkInterface, @NonNull OffloadIntentStore offloadIntentStore, @NonNull OffloadWriter offloadWriter)27 InterfaceOffloadManager( 28 @NonNull String networkInterface, 29 @NonNull OffloadIntentStore offloadIntentStore, 30 @NonNull OffloadWriter offloadWriter) { 31 mNetworkInterface = networkInterface; 32 mOffloadIntentStore = offloadIntentStore; 33 mOffloadWriter = offloadWriter; 34 } 35 onVendorServiceConnected()36 void onVendorServiceConnected() { 37 refreshProtocolResponses(); 38 refreshPassthroughList(); 39 } 40 onAppIdAllowlistUpdated()41 void onAppIdAllowlistUpdated() { 42 refreshProtocolResponses(); 43 refreshPassthroughList(); 44 } 45 onNetworkAvailable()46 void onNetworkAvailable() { 47 String msg = "Network interface {" + mNetworkInterface + "} is connected." + 48 " Offloading all stored data."; 49 Log.d(TAG, msg); 50 mIsNetworkAvailable = true; 51 refreshProtocolResponses(); 52 refreshPassthroughList(); 53 } 54 onNetworkLost()55 void onNetworkLost() { 56 String msg = "Network interface {" + mNetworkInterface + "} was disconnected." 57 + " Clearing all associated data."; 58 Log.d(TAG, msg); 59 mIsNetworkAvailable = false; 60 clearProtocolResponses(); 61 clearPassthroughList(); 62 } 63 onVendorServiceDisconnected()64 void onVendorServiceDisconnected() { 65 mCurrentOffloadKeys.clear(); 66 mCurrentPassthroughQNames.clear(); 67 } 68 refreshProtocolResponses()69 void refreshProtocolResponses() { 70 if (!mIsNetworkAvailable) { 71 return; 72 } 73 applyOffloadIntents(mOffloadIntentStore.getOffloadIntentsForInterface(mNetworkInterface)); 74 } 75 refreshPassthroughList()76 void refreshPassthroughList() { 77 if (!mIsNetworkAvailable) { 78 return; 79 } 80 applyPassthroughIntents( 81 mOffloadIntentStore.getPassthroughIntentsForInterface(mNetworkInterface)); 82 } 83 retrieveAndClearMetrics()84 void retrieveAndClearMetrics() { 85 if (!mIsNetworkAvailable) { 86 return; 87 } 88 if (!mOffloadWriter.isVendorServiceConnected()) { 89 Log.e(TAG, "Vendor service disconnected, cannot apply mDNS offload state"); 90 return; 91 } 92 mOffloadWriter.retrieveAndClearMetrics(mCurrentOffloadKeys); 93 } 94 clearProtocolResponses()95 private void clearProtocolResponses() { 96 applyOffloadIntents(Collections.emptySet()); 97 } 98 clearPassthroughList()99 private void clearPassthroughList() { 100 applyPassthroughIntents(Collections.emptyList()); 101 } 102 applyOffloadIntents(Collection<OffloadIntentStore.OffloadIntent> offloadIntents)103 private void applyOffloadIntents(Collection<OffloadIntentStore.OffloadIntent> offloadIntents) { 104 if (!mOffloadWriter.isVendorServiceConnected()) { 105 Log.e(TAG, "Vendor service disconnected, cannot apply mDNS offload state"); 106 return; 107 } 108 Collection<Integer> deleted = mOffloadWriter.deleteOffloadData(mCurrentOffloadKeys); 109 mCurrentOffloadKeys.removeAll(deleted); 110 Collection<Integer> offloaded = mOffloadWriter.writeOffloadData( 111 mNetworkInterface, offloadIntents); 112 mCurrentOffloadKeys.addAll(offloaded); 113 } 114 applyPassthroughIntents( List<OffloadIntentStore.PassthroughIntent> passthroughIntents)115 private void applyPassthroughIntents( 116 List<OffloadIntentStore.PassthroughIntent> passthroughIntents) { 117 if (!mOffloadWriter.isVendorServiceConnected()){ 118 Log.e(TAG, "Vendor service disconnected, cannot apply mDNS passthrough state"); 119 return; 120 } 121 Collection<String> deleted = mOffloadWriter.deletePassthroughData( 122 mNetworkInterface, mCurrentPassthroughQNames); 123 mCurrentPassthroughQNames.removeAll(deleted); 124 Collection<String> added = mOffloadWriter.writePassthroughData( 125 mNetworkInterface, passthroughIntents); 126 mCurrentPassthroughQNames.addAll(added); 127 } 128 129 @WorkerThread dump(PrintWriter writer)130 void dump(PrintWriter writer) { 131 writer.println("InterfaceOffloadManager[%s]:".formatted(mNetworkInterface)); 132 writer.println("mIsNetworkAvailable=%b".formatted(mIsNetworkAvailable)); 133 writer.println("current offload keys:"); 134 mCurrentOffloadKeys.forEach(key -> writer.println("* %d".formatted(key))); 135 writer.println("current passthrough qnames:"); 136 mCurrentPassthroughQNames.forEach(qname -> writer.println("* %s".formatted(qname))); 137 writer.println(); 138 } 139 140 } 141