• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.wifi.repository;
18 
19 import android.app.PendingIntent;
20 import android.content.Context;
21 import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
22 import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
23 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
24 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
25 import android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback;
26 import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
27 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
28 import android.os.HandlerThread;
29 import android.provider.DeviceConfig;
30 import android.util.Log;
31 
32 import androidx.annotation.NonNull;
33 import androidx.annotation.VisibleForTesting;
34 import androidx.annotation.WorkerThread;
35 import androidx.lifecycle.LiveData;
36 import androidx.lifecycle.MutableLiveData;
37 
38 import com.android.settings.overlay.FeatureFactory;
39 
40 import java.util.List;
41 import java.util.concurrent.Executor;
42 
43 /**
44  * Shared Connectivity Repository for {@link SharedConnectivityManager}
45  */
46 public class SharedConnectivityRepository {
47     private static final String TAG = "SharedConnectivityRepository";
48     private static final String DEVICE_CONFIG_NAMESPACE = "wifi";
49     private static final String DEVICE_CONFIG_KEY = "shared_connectivity_enabled";
50 
51     private Context mAppContext;
52     private SharedConnectivityManager mManager;
53     private ClientCallback mClientCallback = new ClientCallback();
54     private HandlerThread mWorkerThread = new HandlerThread(TAG);
55     private Executor mWorkerExecutor = cmd -> mWorkerThread.getThreadHandler().post(cmd);
56     private Runnable mLaunchSettingsRunnable = () -> handleLaunchSettings();
57     @VisibleForTesting
58     MutableLiveData<SharedConnectivitySettingsState> mSettingsState = new MutableLiveData<>();
59 
SharedConnectivityRepository(@onNull Context appContext)60     public SharedConnectivityRepository(@NonNull Context appContext) {
61         this(appContext, isDeviceConfigEnabled());
62     }
63 
64     @VisibleForTesting
SharedConnectivityRepository(@onNull Context appContext, boolean isConfigEnabled)65     SharedConnectivityRepository(@NonNull Context appContext, boolean isConfigEnabled) {
66         mAppContext = appContext;
67         if (!isConfigEnabled) {
68             return;
69         }
70         mManager = mAppContext.getSystemService(SharedConnectivityManager.class);
71         if (mManager == null) {
72             Log.w(TAG, "Failed to get SharedConnectivityManager");
73             return;
74         }
75         mWorkerThread.start();
76         mManager.registerCallback(mWorkerExecutor, mClientCallback);
77     }
78 
79     /**
80      * Return whether Wi-Fi Shared Connectivity service is available or not.
81      *
82      * @return {@code true} if Wi-Fi Shared Connectivity service is available
83      */
isServiceAvailable()84     public boolean isServiceAvailable() {
85         return mManager != null;
86     }
87 
88     /**
89      * Gets SharedConnectivitySettingsState LiveData
90      */
getSettingsState()91     public LiveData<SharedConnectivitySettingsState> getSettingsState() {
92         return mSettingsState;
93     }
94 
95     /**
96      * Launch Instant Hotspot Settings
97      */
launchSettings()98     public void launchSettings() {
99         mWorkerExecutor.execute(mLaunchSettingsRunnable);
100     }
101 
102     @WorkerThread
103     @VisibleForTesting
handleLaunchSettings()104     void handleLaunchSettings() {
105         if (mManager == null) {
106             return;
107         }
108         SharedConnectivitySettingsState state = mManager.getSettingsState();
109         log("handleLaunchSettings(), state:" + state);
110         if (state == null) {
111             Log.e(TAG, "No SettingsState to launch Instant Hotspot settings");
112             return;
113         }
114         PendingIntent intent = state.getInstantTetherSettingsPendingIntent();
115         if (intent == null) {
116             Log.e(TAG, "No PendingIntent to launch Instant Hotspot settings");
117             return;
118         }
119         sendSettingsIntent(intent);
120     }
121 
122     @WorkerThread
123     @VisibleForTesting
sendSettingsIntent(@onNull PendingIntent intent)124     void sendSettingsIntent(@NonNull PendingIntent intent) {
125         try {
126             log("sendSettingsIntent(), sent intent:" + intent);
127             intent.send();
128         } catch (PendingIntent.CanceledException e) {
129             Log.e(TAG, "Failed to launch Instant Hotspot settings", e);
130         }
131     }
132 
133     @WorkerThread
134     class ClientCallback implements SharedConnectivityClientCallback {
135 
136         @Override
onHotspotNetworkConnectionStatusChanged(HotspotNetworkConnectionStatus status)137         public void onHotspotNetworkConnectionStatusChanged(HotspotNetworkConnectionStatus status) {
138             log("onHotspotNetworkConnectionStatusChanged(), status:" + status);
139         }
140 
141         @Override
onHotspotNetworksUpdated(List<HotspotNetwork> networks)142         public void onHotspotNetworksUpdated(List<HotspotNetwork> networks) {
143             log("onHotspotNetworksUpdated(), networks:" + networks);
144         }
145 
146         @Override
onKnownNetworkConnectionStatusChanged(KnownNetworkConnectionStatus status)147         public void onKnownNetworkConnectionStatusChanged(KnownNetworkConnectionStatus status) {
148             log("onKnownNetworkConnectionStatusChanged(), status:" + status);
149         }
150 
151         @Override
onKnownNetworksUpdated(List<KnownNetwork> networks)152         public void onKnownNetworksUpdated(List<KnownNetwork> networks) {
153             log("onKnownNetworksUpdated(), networks:" + networks);
154         }
155 
156         @Override
onRegisterCallbackFailed(Exception e)157         public void onRegisterCallbackFailed(Exception e) {
158             Log.e(TAG, "onRegisterCallbackFailed(), e:" + e);
159         }
160 
161         @Override
onServiceConnected()162         public void onServiceConnected() {
163             SharedConnectivitySettingsState state = mManager.getSettingsState();
164             Log.d(TAG, "onServiceConnected(), Manager#getSettingsState:" + state);
165             mSettingsState.postValue(state);
166         }
167 
168         @Override
onServiceDisconnected()169         public void onServiceDisconnected() {
170             log("onServiceDisconnected()");
171         }
172 
173         @Override
onSharedConnectivitySettingsChanged(SharedConnectivitySettingsState state)174         public void onSharedConnectivitySettingsChanged(SharedConnectivitySettingsState state) {
175             Log.d(TAG, "onSharedConnectivitySettingsChanged(), state:" + state);
176             mSettingsState.postValue(state);
177         }
178     }
179 
log(String msg)180     private void log(String msg) {
181         FeatureFactory.getFactory(mAppContext).getWifiFeatureProvider().verboseLog(TAG, msg);
182     }
183 
184     /**
185      * Returns true if Shared Connectivity feature is enabled.
186      */
isDeviceConfigEnabled()187     public static boolean isDeviceConfigEnabled() {
188         return DeviceConfig.getBoolean(DEVICE_CONFIG_NAMESPACE, DEVICE_CONFIG_KEY, false);
189     }
190 }
191