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 clearProtocolResponses()84 private void clearProtocolResponses() { 85 applyOffloadIntents(Collections.emptySet()); 86 } 87 clearPassthroughList()88 private void clearPassthroughList() { 89 applyPassthroughIntents(Collections.emptyList()); 90 } 91 applyOffloadIntents(Collection<OffloadIntentStore.OffloadIntent> offloadIntents)92 private void applyOffloadIntents(Collection<OffloadIntentStore.OffloadIntent> offloadIntents) { 93 if (!mOffloadWriter.isVendorServiceConnected()) { 94 Log.e(TAG, "Vendor service disconnected, cannot apply mDNS offload state"); 95 return; 96 } 97 Collection<Integer> deleted = mOffloadWriter.deleteOffloadData(mCurrentOffloadKeys); 98 mCurrentOffloadKeys.removeAll(deleted); 99 Collection<Integer> offloaded = mOffloadWriter.writeOffloadData( 100 mNetworkInterface, offloadIntents); 101 mCurrentOffloadKeys.addAll(offloaded); 102 } 103 applyPassthroughIntents( List<OffloadIntentStore.PassthroughIntent> passthroughIntents)104 private void applyPassthroughIntents( 105 List<OffloadIntentStore.PassthroughIntent> passthroughIntents) { 106 if (!mOffloadWriter.isVendorServiceConnected()){ 107 Log.e(TAG, "Vendor service disconnected, cannot apply mDNS passthrough state"); 108 return; 109 } 110 Collection<String> deleted = mOffloadWriter.deletePassthroughData( 111 mNetworkInterface, mCurrentPassthroughQNames); 112 mCurrentPassthroughQNames.removeAll(deleted); 113 Collection<String> added = mOffloadWriter.writePassthroughData( 114 mNetworkInterface, passthroughIntents); 115 mCurrentPassthroughQNames.addAll(added); 116 } 117 118 @WorkerThread dump(PrintWriter writer)119 void dump(PrintWriter writer) { 120 writer.println("InterfaceOffloadManager[%s]:".formatted(mNetworkInterface)); 121 writer.println("mIsNetworkAvailable=%b".formatted(mIsNetworkAvailable)); 122 writer.println("current offload keys:"); 123 mCurrentOffloadKeys.forEach(key -> writer.println("* %d".formatted(key))); 124 writer.println("current passthrough qnames:"); 125 mCurrentPassthroughQNames.forEach(qname -> writer.println("* %s".formatted(qname))); 126 writer.println(); 127 } 128 129 } 130