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