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