1 /* 2 * Copyright (C) 2015 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.vpn2; 18 19 import android.app.admin.DevicePolicyManager; 20 import android.content.Context; 21 import android.content.pm.PackageInfo; 22 import android.content.pm.PackageManager; 23 import android.graphics.drawable.Drawable; 24 import android.os.UserHandle; 25 26 import androidx.preference.Preference; 27 28 import com.android.internal.net.LegacyVpnInfo; 29 import com.android.internal.net.VpnConfig; 30 import com.android.settingslib.RestrictedLockUtils; 31 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 32 import com.android.settings.R; 33 34 /** 35 * {@link androidx.preference.Preference} containing information about a VPN 36 * application. Tracks the package name and connection state. 37 */ 38 public class AppPreference extends ManageablePreference { 39 public static final int STATE_CONNECTED = LegacyVpnInfo.STATE_CONNECTED; 40 public static final int STATE_DISCONNECTED = STATE_NONE; 41 42 private final String mPackageName; 43 private final String mName; 44 AppPreference(Context context, int userId, String packageName)45 public AppPreference(Context context, int userId, String packageName) { 46 super(context, null /* attrs */, R.style.VpnAppManagementPreferenceStyle, 0); 47 super.setUserId(userId); 48 49 mPackageName = packageName; 50 disableIfConfiguredByAdmin(); 51 52 // Fetch icon and VPN label 53 String label = packageName; 54 Drawable icon = null; 55 try { 56 // Make all calls to the package manager as the appropriate user. 57 Context userContext = getUserContext(); 58 PackageManager pm = userContext.getPackageManager(); 59 // The nested catch block is for the case that the app doesn't exist, so we can fall 60 // back to the default activity icon. 61 try { 62 PackageInfo pkgInfo = pm.getPackageInfo(mPackageName, 0 /* flags */); 63 if (pkgInfo != null) { 64 icon = pkgInfo.applicationInfo.loadIcon(pm); 65 label = VpnConfig.getVpnLabel(userContext, mPackageName).toString(); 66 } 67 } catch (PackageManager.NameNotFoundException pkgNotFound) { 68 // Use default app label and icon as fallback 69 } 70 if (icon == null) { 71 icon = pm.getDefaultActivityIcon(); 72 } 73 } catch (PackageManager.NameNotFoundException userNotFound) { 74 // No user, no useful information to obtain. Quietly fail. 75 } 76 mName = label; 77 78 setTitle(mName); 79 setIcon(icon); 80 } 81 82 /** 83 * Disable this preference if VPN is set as always on by a profile or device owner. 84 * NB: it should be called after super.setUserId() otherwise admin information can be lost. 85 */ disableIfConfiguredByAdmin()86 private void disableIfConfiguredByAdmin() { 87 if (isDisabledByAdmin()) { 88 // Already disabled due to user restriction. 89 return; 90 } 91 final DevicePolicyManager dpm = getContext() 92 .createContextAsUser(UserHandle.of(getUserId()), /* flags= */ 0) 93 .getSystemService(DevicePolicyManager.class); 94 if (mPackageName.equals(dpm.getAlwaysOnVpnPackage())) { 95 final EnforcedAdmin admin = RestrictedLockUtils.getProfileOrDeviceOwner( 96 getContext(), UserHandle.of(mUserId)); 97 setDisabledByAdmin(admin); 98 } 99 } 100 getPackageInfo()101 public PackageInfo getPackageInfo() { 102 try { 103 PackageManager pm = getUserContext().getPackageManager(); 104 return pm.getPackageInfo(mPackageName, 0 /* flags */); 105 } catch (PackageManager.NameNotFoundException nnfe) { 106 return null; 107 } 108 } 109 getLabel()110 public String getLabel() { 111 return mName; 112 } 113 getPackageName()114 public String getPackageName() { 115 return mPackageName; 116 } 117 getUserContext()118 private Context getUserContext() throws PackageManager.NameNotFoundException { 119 UserHandle user = UserHandle.of(mUserId); 120 return getContext().createPackageContextAsUser( 121 getContext().getPackageName(), 0 /* flags */, user); 122 } 123 compareTo(Preference preference)124 public int compareTo(Preference preference) { 125 if (preference instanceof AppPreference) { 126 AppPreference another = (AppPreference) preference; 127 int result; 128 if ((result = another.mState - mState) == 0 && 129 (result = mName.compareToIgnoreCase(another.mName)) == 0 && 130 (result = mPackageName.compareTo(another.mPackageName)) == 0) { 131 result = mUserId - another.mUserId; 132 } 133 return result; 134 } else if (preference instanceof LegacyVpnPreference) { 135 // Use comparator from ConfigPreference 136 LegacyVpnPreference another = (LegacyVpnPreference) preference; 137 return -another.compareTo(this); 138 } else { 139 return super.compareTo(preference); 140 } 141 } 142 } 143 144