5050import com .termux .terminal .TerminalSessionClient ;
5151
5252import java .util .ArrayList ;
53+ import java .util .HashSet ;
5354import java .util .List ;
55+ import java .util .Set ;
5456
5557/**
5658 * A service holding a list of {@link TermuxSession} in {@link TermuxShellManager#mTermuxSessions} and background {@link AppShell}
@@ -77,11 +79,12 @@ class LocalBinder extends Binder {
7779 private final Handler mHandler = new Handler ();
7880
7981
80- /** The full implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
81- * that holds activity references for activity related functions.
82- * Note that the service may often outlive the activity, so need to clear this reference.
82+ /** The full implementations of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
83+ * that hold activity references for activity related functions. In multi-window mode, multiple
84+ * activities may be bound simultaneously. Note that the service may often outlive the activities,
85+ * so need to clear these references when activities are destroyed.
8386 */
84- private TermuxTerminalSessionActivityClient mTermuxTerminalSessionActivityClient ;
87+ private final Set < TermuxTerminalSessionActivityClient > mActivityClients = new HashSet <>() ;
8588
8689 /** The basic implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
8790 * that does not hold activity references and only a service reference.
@@ -195,7 +198,7 @@ public boolean onUnbind(Intent intent) {
195198 // Since we cannot rely on {@link TermuxActivity.onDestroy()} to always complete,
196199 // we unset clients here as well if it failed, so that we do not leave service and session
197200 // clients with references to the activity.
198- if (mTermuxTerminalSessionActivityClient != null )
201+ if (! mActivityClients . isEmpty () )
199202 unsetTermuxTerminalSessionClient ();
200203 return false ;
201204 }
@@ -612,10 +615,8 @@ public synchronized TermuxSession createTermuxSession(ExecutionCommand execution
612615 if (executionCommand .isPluginExecutionCommand )
613616 mShellManager .mPendingPluginExecutionCommands .remove (executionCommand );
614617
615- // Notify {@link TermuxSessionsListViewController} that sessions list has been updated if
616- // activity in is foreground
617- if (mTermuxTerminalSessionActivityClient != null )
618- mTermuxTerminalSessionActivityClient .termuxSessionListNotifyUpdated ();
618+ // Notify all activities that sessions list has been updated
619+ notifyAllSessionListsUpdated ();
619620
620621 updateNotification ();
621622
@@ -649,10 +650,8 @@ public void onTermuxSessionExited(final TermuxSession termuxSession) {
649650
650651 mShellManager .mTermuxSessions .remove (termuxSession );
651652
652- // Notify {@link TermuxSessionsListViewController} that sessions list has been updated if
653- // activity in is foreground
654- if (mTermuxTerminalSessionActivityClient != null )
655- mTermuxTerminalSessionActivityClient .termuxSessionListNotifyUpdated ();
653+ // Notify all activities that sessions list has been updated
654+ notifyAllSessionListsUpdated ();
656655 }
657656
658657 updateNotification ();
@@ -687,8 +686,8 @@ private void handleSessionAction(int sessionAction, TerminalSession newTerminalS
687686 switch (sessionAction ) {
688687 case TERMUX_SERVICE .VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY :
689688 setCurrentStoredTerminalSession (newTerminalSession );
690- if (mTermuxTerminalSessionActivityClient != null )
691- mTermuxTerminalSessionActivityClient .setCurrentSession (newTerminalSession );
689+ if (! mActivityClients . isEmpty () )
690+ mActivityClients . iterator (). next () .setCurrentSession (newTerminalSession );
692691 startTermuxActivity ();
693692 break ;
694693 case TERMUX_SERVICE .VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_OPEN_ACTIVITY :
@@ -698,8 +697,8 @@ private void handleSessionAction(int sessionAction, TerminalSession newTerminalS
698697 break ;
699698 case TERMUX_SERVICE .VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_DONT_OPEN_ACTIVITY :
700699 setCurrentStoredTerminalSession (newTerminalSession );
701- if (mTermuxTerminalSessionActivityClient != null )
702- mTermuxTerminalSessionActivityClient .setCurrentSession (newTerminalSession );
700+ if (! mActivityClients . isEmpty () )
701+ mActivityClients . iterator (). next () .setCurrentSession (newTerminalSession );
703702 break ;
704703 case TERMUX_SERVICE .VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_DONT_OPEN_ACTIVITY :
705704 if (getTermuxSessionsSize () == 1 )
@@ -731,40 +730,44 @@ private void startTermuxActivity() {
731730
732731
733732
734- /** If {@link TermuxActivity} has not bound to the {@link TermuxService} yet or is destroyed, then
733+ /** If no {@link TermuxActivity} has bound to the {@link TermuxService} yet or all are destroyed, then
735734 * interface functions requiring the activity should not be available to the terminal sessions,
736735 * so we just return the {@link #mTermuxTerminalSessionServiceClient}. Once {@link TermuxActivity} bind
737- * callback is received, it should call {@link #setTermuxTerminalSessionClient} to set the
738- * {@link TermuxService#mTermuxTerminalSessionActivityClient } so that further terminal sessions are directly
739- * passed the {@link TermuxTerminalSessionActivityClient} object which fully implements the
736+ * callback is received, it should call {@link #setTermuxTerminalSessionClient} to add its client
737+ * to {@link TermuxService#mActivityClients } so that further terminal sessions are directly
738+ * passed a {@link TermuxTerminalSessionActivityClient} object which fully implements the
740739 * {@link TerminalSessionClient} interface.
741740 *
742- * @return Returns the {@link TermuxTerminalSessionActivityClient} if {@link TermuxActivity} has bound with
743- * {@link TermuxService}, otherwise {@link TermuxTerminalSessionServiceClient}.
741+ * @return Returns the first available {@link TermuxTerminalSessionActivityClient} if any {@link TermuxActivity}
742+ * has bound with {@link TermuxService}, otherwise {@link TermuxTerminalSessionServiceClient}.
744743 */
745744 public synchronized TermuxTerminalSessionClientBase getTermuxTerminalSessionClient () {
746- if (mTermuxTerminalSessionActivityClient != null )
747- return mTermuxTerminalSessionActivityClient ;
745+ if (! mActivityClients . isEmpty () )
746+ return mActivityClients . iterator (). next () ;
748747 else
749748 return mTermuxTerminalSessionServiceClient ;
750749 }
751750
752- /** This should be called when {@link TermuxActivity#onServiceConnected} is called to set the
753- * {@link TermuxService#mTermuxTerminalSessionActivityClient} variable and update the {@link TerminalSession}
754- * and {@link TerminalEmulator} clients in case they were passed {@link TermuxTerminalSessionServiceClient}
755- * earlier.
751+ /** This should be called when {@link TermuxActivity#onServiceConnected} is called to add
752+ * the activity's client to {@link TermuxService#mActivityClients}. In multi-window mode,
753+ * multiple activities may be bound simultaneously.
756754 *
757755 * @param termuxTerminalSessionActivityClient The {@link TermuxTerminalSessionActivityClient} object that fully
758756 * implements the {@link TerminalSessionClient} interface.
759757 */
760758 public synchronized void setTermuxTerminalSessionClient (TermuxTerminalSessionActivityClient termuxTerminalSessionActivityClient ) {
761- mTermuxTerminalSessionActivityClient = termuxTerminalSessionActivityClient ;
759+ mActivityClients . add ( termuxTerminalSessionActivityClient ) ;
762760
763761 // Don't update all sessions' clients here - in multi-window mode, each activity
764762 // should only set the client for its own attached session. The client is set
765763 // when setCurrentSession() is called in TermuxTerminalSessionActivityClient.
766764 }
767765
766+ /** Remove an activity client when its activity is destroyed. */
767+ public synchronized void removeTermuxTerminalSessionClient (TermuxTerminalSessionActivityClient client ) {
768+ mActivityClients .remove (client );
769+ }
770+
768771 /** This should be called when {@link TermuxActivity} has been destroyed and in {@link #onUnbind(Intent)}
769772 * so that the {@link TermuxService} and {@link TerminalSession} and {@link TerminalEmulator}
770773 * clients do not hold an activity references.
@@ -773,7 +776,7 @@ public synchronized void unsetTermuxTerminalSessionClient() {
773776 for (int i = 0 ; i < mShellManager .mTermuxSessions .size (); i ++)
774777 mShellManager .mTermuxSessions .get (i ).getTerminalSession ().updateTerminalSessionClient (mTermuxTerminalSessionServiceClient );
775778
776- mTermuxTerminalSessionActivityClient = null ;
779+ mActivityClients . clear () ;
777780 }
778781
779782 /** Reset a specific session's client to the service client. Used when an activity is destroyed
@@ -784,6 +787,14 @@ public synchronized void resetSessionClient(TerminalSession session) {
784787 }
785788 }
786789
790+ /** Notify all bound activities to update their session lists. Used when session attachment
791+ * state changes in multi-window mode. */
792+ public synchronized void notifyAllSessionListsUpdated () {
793+ for (TermuxTerminalSessionActivityClient client : mActivityClients ) {
794+ client .termuxSessionListNotifyUpdated ();
795+ }
796+ }
797+
787798
788799
789800
0 commit comments