Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e13caf9 authored by Robin Lee's avatar Robin Lee Committed by Android (Google) Code Review
Browse files

Merge "vpn2: show third-party VPN services"

parents 6d610615 2bd92d5d
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    <View
        android:id="@+id/divider_manage"
        android:layout_width="2dip"
        android:layout_height="match_parent"
        android:layout_marginTop="5dip"
        android:layout_marginBottom="5dip"
        android:background="@android:drawable/divider_horizontal_dark" />
    <ImageView
        android:id="@+id/manage"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:paddingStart="16dip"
        android:paddingEnd="16dip"
        android:src="@drawable/ic_sysbar_quicksettings"
        android:contentDescription="@string/settings_label"
        android:layout_gravity="center"
        android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
    <LinearLayout android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="3mm">
            android:padding="8dp">

        <LinearLayout android:id="@+id/editor"
                android:layout_width="match_parent"
+10 −0
Original line number Diff line number Diff line
@@ -5241,14 +5241,24 @@

    <!-- Button label to cancel changing a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_cancel">Cancel</string>
    <!-- Button label to finish editing a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_done">Dismiss</string>
    <!-- Button label to save a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_save">Save</string>
    <!-- Button label to connect to a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_connect">Connect</string>
    <!-- Dialog title to edit a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_edit">Edit VPN profile</string>
    <!-- Button label to forget a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_forget">Forget</string>
    <!-- Dialog title to connect to a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_connect_to">Connect to <xliff:g id="profile" example="School">%s</xliff:g></string>
    <!-- Dialog message body to disconnect from a VPN profile. -->
    <string name="vpn_disconnect_confirm">Disconnect this VPN.</string>
    <!-- Button label to disconnect from a VPN profile. [CHAR LIMIT=40] -->
    <string name="vpn_disconnect">Disconnect</string>
    <!-- Field label to show the version number for a VPN app. [CHAR LIMIT=40] -->
    <string name="vpn_version">Version <xliff:g id="version" example="3.3.0">%s</xliff:g></string>

    <!-- Preference title for VPN settings. [CHAR LIMIT=40] -->
    <string name="vpn_title">VPN</string>
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.vpn2;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.android.internal.net.VpnConfig;
import com.android.settings.R;

/**
 * UI for managing the connection controlled by an app.
 *
 * Among the actions available are (depending on context):
 * <ul>
 *   <li><strong>Forget</strong>: revoke the managing app's VPN permission</li>
 *   <li><strong>Dismiss</strong>: continue to use the VPN</li>
 * </ul>
 *
 * {@see ConfigDialog}
 */
class AppDialog extends AlertDialog implements DialogInterface.OnClickListener {
    private final PackageInfo mPkgInfo;
    private final Listener mListener;
    private final boolean mConnected;

    AppDialog(Context context, Listener listener, PackageInfo pkgInfo, boolean connected) {
        super(context);

        mListener = listener;
        mPkgInfo = pkgInfo;
        mConnected = connected;
    }

    public final PackageInfo getPackageInfo() {
        return mPkgInfo;
    }

    @Override
    protected void onCreate(Bundle savedState) {
        CharSequence vpnName;
        try {
            vpnName = VpnConfig.getVpnLabel(getContext(), mPkgInfo.packageName);
        } catch (PackageManager.NameNotFoundException ex) {
            vpnName = mPkgInfo.packageName;
        }

        setTitle(vpnName);
        setMessage(getContext().getString(R.string.vpn_version, mPkgInfo.versionName));

        createButtons();
        super.onCreate(savedState);
    }

    protected void createButtons() {
        Context context = getContext();

        if (mConnected) {
            // Forget the network
            setButton(DialogInterface.BUTTON_NEGATIVE,
                    context.getString(R.string.vpn_forget), this);
        }

        // Dismiss
        setButton(DialogInterface.BUTTON_POSITIVE,
                context.getString(R.string.vpn_done), this);
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_NEGATIVE) {
            mListener.onForget(dialog);
        }
        dismiss();
    }

    public interface Listener {
        public void onForget(DialogInterface dialog);
    }
}
+136 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.vpn2;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.IConnectivityManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import com.android.internal.net.VpnConfig;
import com.android.settings.R;

/**
 * Fragment wrapper around an {@link AppDialog}.
 */
public class AppDialogFragment extends DialogFragment implements AppDialog.Listener {
    private static final String TAG_APP_DIALOG = "vpnappdialog";
    private static final String TAG = "AppDialogFragment";

    private static final String ARG_MANAGING = "managing";
    private static final String ARG_PACKAGE = "package";
    private static final String ARG_CONNECTED = "connected";

    private final IConnectivityManager mService = IConnectivityManager.Stub.asInterface(
            ServiceManager.getService(Context.CONNECTIVITY_SERVICE));

    public static void show(VpnSettings parent, PackageInfo pkgInfo, boolean managing,
            boolean connected) {
        if (!parent.isAdded()) return;

        Bundle args = new Bundle();
        args.putParcelable(ARG_PACKAGE, pkgInfo);
        args.putBoolean(ARG_MANAGING, managing);
        args.putBoolean(ARG_CONNECTED, connected);

        final AppDialogFragment frag = new AppDialogFragment();
        frag.setArguments(args);
        frag.setTargetFragment(parent, 0);
        frag.show(parent.getFragmentManager(), TAG_APP_DIALOG);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Bundle args = getArguments();
        PackageInfo pkgInfo = (PackageInfo) args.getParcelable(ARG_PACKAGE);
        boolean managing = args.getBoolean(ARG_MANAGING);
        boolean connected = args.getBoolean(ARG_CONNECTED);

        if (managing) {
            return new AppDialog(getActivity(), this, pkgInfo, connected);
        } else {
            // Build an AlertDialog with an option to disconnect.

            CharSequence vpnName;
            try {
                vpnName = VpnConfig.getVpnLabel(getActivity(), pkgInfo.packageName);
            } catch (PackageManager.NameNotFoundException ex) {
                vpnName = pkgInfo.packageName;
            }

            AlertDialog.Builder dlog = new AlertDialog.Builder(getActivity())
                    .setTitle(vpnName)
                    .setMessage(getActivity().getString(R.string.vpn_disconnect_confirm))
                    .setNegativeButton(getActivity().getString(R.string.vpn_cancel), null);

            if (connected) {
                dlog.setPositiveButton(getActivity().getString(R.string.vpn_disconnect),
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                onDisconnect(dialog);
                            }
                        });
            }
            return dlog.create();
        }
    }

    @Override
    public void dismiss() {
        ((VpnSettings) getTargetFragment()).update();
        super.dismiss();
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        dismiss();
        super.onCancel(dialog);
    }

    @Override
    public void onForget(final DialogInterface dialog) {
        PackageInfo pkgInfo = (PackageInfo) getArguments().getParcelable(ARG_PACKAGE);
        final String pkg = pkgInfo.packageName;
        try {
            VpnConfig vpnConfig = mService.getVpnConfig();
            if (vpnConfig != null && pkg.equals(vpnConfig.user) && !vpnConfig.legacy) {
                mService.setVpnPackageAuthorization(false);
                onDisconnect(dialog);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to forget authorization for " + pkg, e);
        }
    }

    private void onDisconnect(final DialogInterface dialog) {
        PackageInfo pkgInfo = (PackageInfo) getArguments().getParcelable(ARG_PACKAGE);
        try {
            mService.prepareVpn(pkgInfo.packageName, VpnConfig.LEGACY_VPN);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to disconnect package " + pkgInfo.packageName, e);
        }
    }
}
Loading