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
17package com.android.settings.vpn2;
18
19import android.app.AppGlobals;
20import android.content.Context;
21import android.content.pm.PackageInfo;
22import android.content.pm.PackageManager;
23import android.graphics.drawable.Drawable;
24import android.os.RemoteException;
25import android.os.UserHandle;
26import android.preference.Preference;
27import android.view.View.OnClickListener;
28
29import com.android.internal.net.LegacyVpnInfo;
30import com.android.internal.net.VpnConfig;
31import com.android.settings.R;
32
33/**
34 * {@link android.preference.Preference} containing information about a VPN
35 * application. Tracks the package name and connection state.
36 */
37public class AppPreference extends ManageablePreference {
38    public static final int STATE_CONNECTED = LegacyVpnInfo.STATE_CONNECTED;
39    public static final int STATE_DISCONNECTED = LegacyVpnInfo.STATE_DISCONNECTED;
40
41    private int mState = STATE_DISCONNECTED;
42    private String mPackageName;
43    private String mName;
44    private int mUid;
45
46    public AppPreference(Context context, OnClickListener onManage, final String packageName,
47            int uid) {
48        super(context, null /* attrs */, onManage);
49        mPackageName = packageName;
50        mUid = uid;
51        update();
52    }
53
54    public PackageInfo getPackageInfo() {
55        UserHandle user = new UserHandle(UserHandle.getUserId(mUid));
56        try {
57            PackageManager pm = getUserContext().getPackageManager();
58            return pm.getPackageInfo(mPackageName, 0 /* flags */);
59        } catch (PackageManager.NameNotFoundException nnfe) {
60            return null;
61        }
62    }
63
64    public String getLabel() {
65        return mName;
66    }
67
68    public String getPackageName() {
69        return mPackageName;
70    }
71
72    public int getUid() {
73        return mUid;
74    }
75
76    public int getState() {
77        return mState;
78    }
79
80    public void setState(int state) {
81        mState = state;
82        update();
83    }
84
85    private void update() {
86        final String[] states = getContext().getResources().getStringArray(R.array.vpn_states);
87        setSummary(mState != STATE_DISCONNECTED ? states[mState] : "");
88
89        mName = mPackageName;
90        Drawable icon = null;
91
92        try {
93            // Make all calls to the package manager as the appropriate user.
94            Context userContext = getUserContext();
95            PackageManager pm = userContext.getPackageManager();
96            // Fetch icon and VPN label- the nested catch block is for the case that the app doesn't
97            // exist, in which case we can fall back to the default activity icon for an activity in
98            // that user.
99            try {
100                PackageInfo pkgInfo = pm.getPackageInfo(mPackageName, 0 /* flags */);
101                if (pkgInfo != null) {
102                    icon = pkgInfo.applicationInfo.loadIcon(pm);
103                    mName = VpnConfig.getVpnLabel(userContext, mPackageName).toString();
104                }
105            } catch (PackageManager.NameNotFoundException pkgNotFound) {
106                // Use default app label and icon as fallback
107            }
108            if (icon == null) {
109                icon = pm.getDefaultActivityIcon();
110            }
111        } catch (PackageManager.NameNotFoundException userNotFound) {
112            // No user, no useful information to obtain. Quietly fail.
113        }
114        setTitle(mName);
115        setIcon(icon);
116
117        notifyHierarchyChanged();
118    }
119
120    private Context getUserContext() throws PackageManager.NameNotFoundException {
121        UserHandle user = new UserHandle(UserHandle.getUserId(mUid));
122        return getContext().createPackageContextAsUser(
123                getContext().getPackageName(), 0 /* flags */, user);
124    }
125
126    public int compareTo(Preference preference) {
127        if (preference instanceof AppPreference) {
128            AppPreference another = (AppPreference) preference;
129            int result;
130            if ((result = another.mState - mState) == 0 &&
131                    (result = mName.compareToIgnoreCase(another.mName)) == 0 &&
132                    (result = mPackageName.compareTo(another.mPackageName)) == 0) {
133                result = mUid - another.mUid;
134            }
135            return result;
136        } else if (preference instanceof ConfigPreference) {
137            // Use comparator from ConfigPreference
138            ConfigPreference another = (ConfigPreference) preference;
139            return -another.compareTo(this);
140        } else {
141            return super.compareTo(preference);
142        }
143    }
144}
145
146