1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed urnder 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 package android.net;
17 
18 import android.annotation.IntDef;
19 import android.annotation.NonNull;
20 import android.annotation.RequiresPermission;
21 import android.annotation.SystemApi;
22 import android.annotation.TestApi;
23 import android.os.IBinder;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.os.RemoteException;
27 
28 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
29 
30 /**
31  * A class allowing apps handling the {@link ConnectivityManager#ACTION_CAPTIVE_PORTAL_SIGN_IN}
32  * activity to indicate to the system different outcomes of captive portal sign in.  This class is
33  * passed as an extra named {@link ConnectivityManager#EXTRA_CAPTIVE_PORTAL} with the
34  * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} activity.
35  */
36 public class CaptivePortal implements Parcelable {
37     /**
38      * Response code from the captive portal application, indicating that the portal was dismissed
39      * and the network should be re-validated.
40      * @see ICaptivePortal#appResponse(int)
41      * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int)
42      * @hide
43      */
44     @SystemApi
45     @TestApi
46     public static final int APP_RETURN_DISMISSED    = 0;
47     /**
48      * Response code from the captive portal application, indicating that the user did not login and
49      * does not want to use the captive portal network.
50      * @see ICaptivePortal#appResponse(int)
51      * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int)
52      * @hide
53      */
54     @SystemApi
55     @TestApi
56     public static final int APP_RETURN_UNWANTED     = 1;
57     /**
58      * Response code from the captive portal application, indicating that the user does not wish to
59      * login but wants to use the captive portal network as-is.
60      * @see ICaptivePortal#appResponse(int)
61      * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int)
62      * @hide
63      */
64     @SystemApi
65     @TestApi
66     public static final int APP_RETURN_WANTED_AS_IS = 2;
67     /** Event offset of request codes from captive portal application. */
68     private static final int APP_REQUEST_BASE = 100;
69     /**
70      * Request code from the captive portal application, indicating that the network condition may
71      * have changed and the network should be re-validated.
72      * @see ICaptivePortal#appRequest(int)
73      * @see android.net.INetworkMonitor#forceReevaluation(int)
74      * @hide
75      */
76     @SystemApi
77     @TestApi
78     public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0;
79 
80     private final IBinder mBinder;
81 
82     /** @hide */
83     @IntDef(value = {
84         MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
85         MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_DISMISSED,
86         MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_UNWANTED,
87         MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_WANTED_AS_IS,
88         MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR,
89     })
90     public @interface EventId {
91     }
92 
93     /** @hide */
CaptivePortal(@onNull IBinder binder)94     public CaptivePortal(@NonNull IBinder binder) {
95         mBinder = binder;
96     }
97 
98     @Override
describeContents()99     public int describeContents() {
100         return 0;
101     }
102 
103     @Override
writeToParcel(Parcel out, int flags)104     public void writeToParcel(Parcel out, int flags) {
105         out.writeStrongBinder(mBinder);
106     }
107 
108     public static final @android.annotation.NonNull Parcelable.Creator<CaptivePortal> CREATOR
109             = new Parcelable.Creator<CaptivePortal>() {
110         @Override
111         public CaptivePortal createFromParcel(Parcel in) {
112             return new CaptivePortal(in.readStrongBinder());
113         }
114 
115         @Override
116         public CaptivePortal[] newArray(int size) {
117             return new CaptivePortal[size];
118         }
119     };
120 
121     /**
122      * Indicate to the system that the captive portal has been
123      * dismissed.  In response the framework will re-evaluate the network's
124      * connectivity and might take further action thereafter.
125      */
reportCaptivePortalDismissed()126     public void reportCaptivePortalDismissed() {
127         try {
128             ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_DISMISSED);
129         } catch (RemoteException e) {
130         }
131     }
132 
133     /**
134      * Indicate to the system that the user does not want to pursue signing in to the
135      * captive portal and the system should continue to prefer other networks
136      * without captive portals for use as the default active data network.  The
137      * system will not retest the network for a captive portal so as to avoid
138      * disturbing the user with further sign in to network notifications.
139      */
ignoreNetwork()140     public void ignoreNetwork() {
141         try {
142             ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_UNWANTED);
143         } catch (RemoteException e) {
144         }
145     }
146 
147     /**
148      * Indicate to the system the user wants to use this network as is, even though
149      * the captive portal is still in place.  The system will treat the network
150      * as if it did not have a captive portal when selecting the network to use
151      * as the default active data network. This may result in this network
152      * becoming the default active data network, which could disrupt network
153      * connectivity for apps because the captive portal is still in place.
154      * @hide
155      */
156     @SystemApi
157     @TestApi
useNetwork()158     public void useNetwork() {
159         try {
160             ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_WANTED_AS_IS);
161         } catch (RemoteException e) {
162         }
163     }
164 
165     /**
166      * Request that the system reevaluates the captive portal status.
167      * @hide
168      */
169     @SystemApi
170     @TestApi
171     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
reevaluateNetwork()172     public void reevaluateNetwork() {
173         try {
174             ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED);
175         } catch (RemoteException e) {
176         }
177     }
178 
179     /**
180      * Log a captive portal login event.
181      * @param eventId one of the CAPTIVE_PORTAL_LOGIN_* constants in metrics_constants.proto.
182      * @param packageName captive portal application package name.
183      * @hide
184      */
185     @SystemApi
186     @TestApi
logEvent(@ventId int eventId, @NonNull String packageName)187     public void logEvent(@EventId int eventId, @NonNull String packageName) {
188         try {
189             ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
190         } catch (RemoteException e) {
191         }
192     }
193 }
194