1 /*
2  * Copyright (C) 2017 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.vpndialogs;
18 
19 import android.content.Context;
20 import android.content.DialogInterface;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.net.IConnectivityManager;
24 import android.os.Bundle;
25 import android.os.RemoteException;
26 import android.os.ServiceManager;
27 import android.os.UserHandle;
28 import android.provider.Settings;
29 import android.text.SpannableStringBuilder;
30 import android.text.method.LinkMovementMethod;
31 import android.text.style.ClickableSpan;
32 import android.util.Log;
33 import android.view.View;
34 import android.view.WindowManager;
35 import android.widget.TextView;
36 
37 import com.android.internal.app.AlertActivity;
38 import com.android.internal.net.VpnConfig;
39 
40 public class AlwaysOnDisconnectedDialog extends AlertActivity
41         implements DialogInterface.OnClickListener{
42 
43     private static final String TAG = "VpnDisconnected";
44 
45     private IConnectivityManager mService;
46     private int mUserId;
47     private String mVpnPackage;
48 
49     @Override
onCreate(Bundle savedInstanceState)50     public void onCreate(Bundle savedInstanceState) {
51         super.onCreate(savedInstanceState);
52 
53         mService = IConnectivityManager.Stub.asInterface(
54                 ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
55         mUserId = UserHandle.myUserId();
56         mVpnPackage = getAlwaysOnVpnPackage();
57         if (mVpnPackage == null) {
58             finish();
59             return;
60         }
61 
62         View view = View.inflate(this, R.layout.always_on_disconnected, null);
63         TextView messageView = view.findViewById(R.id.message);
64         messageView.setText(getMessage(getIntent().getBooleanExtra("lockdown", false)));
65         messageView.setMovementMethod(LinkMovementMethod.getInstance());
66 
67         mAlertParams.mTitle = getString(R.string.always_on_disconnected_title);
68         mAlertParams.mPositiveButtonText = getString(R.string.open_app);
69         mAlertParams.mPositiveButtonListener = this;
70         mAlertParams.mNegativeButtonText = getString(R.string.dismiss);
71         mAlertParams.mNegativeButtonListener = this;
72         mAlertParams.mCancelable = false;
73         mAlertParams.mView = view;
74         setupAlert();
75 
76         getWindow().setCloseOnTouchOutside(false);
77         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
78         getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
79     }
80 
81     @Override
onClick(DialogInterface dialog, int which)82     public void onClick(DialogInterface dialog, int which) {
83         switch (which) {
84             case BUTTON_POSITIVE:
85                 PackageManager pm = getPackageManager();
86                 final Intent intent = pm.getLaunchIntentForPackage(mVpnPackage);
87                 if (intent != null) {
88                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
89                     startActivity(intent);
90                 }
91                 finish();
92                 break;
93             case BUTTON_NEGATIVE:
94                 finish();
95                 break;
96             default:
97                 break;
98         }
99     }
100 
getAlwaysOnVpnPackage()101     private String getAlwaysOnVpnPackage() {
102         try {
103             return mService.getAlwaysOnVpnPackage(mUserId);
104         } catch (RemoteException e) {
105             Log.e(TAG, "Can't getAlwaysOnVpnPackage()", e);
106             return null;
107         }
108     }
109 
getVpnLabel()110     private CharSequence getVpnLabel() {
111         try {
112             return VpnConfig.getVpnLabel(this, mVpnPackage);
113         } catch (PackageManager.NameNotFoundException e) {
114             Log.w(TAG, "Can't getVpnLabel() for " + mVpnPackage, e);
115             return mVpnPackage;
116         }
117     }
118 
getMessage(boolean isLockdown)119     private CharSequence getMessage(boolean isLockdown) {
120         final SpannableStringBuilder message = new SpannableStringBuilder();
121         final int baseMessageResId = isLockdown
122                 ? R.string.always_on_disconnected_message_lockdown
123                 : R.string.always_on_disconnected_message;
124         message.append(getString(baseMessageResId, getVpnLabel()));
125         message.append(getString(R.string.always_on_disconnected_message_separator));
126         message.append(getString(R.string.always_on_disconnected_message_settings_link),
127                 new VpnSpan(), 0 /*flags*/);
128         return message;
129     }
130 
131     private class VpnSpan extends ClickableSpan {
132         @Override
onClick(View unused)133         public void onClick(View unused) {
134             final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
135             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
136             startActivity(intent);
137         }
138     }
139 }
140