blob: 2fd769b42a2be0e113411d38062e2cf32bdf2a7d [file] [log] [blame]
Dianne Hackborn28429032010-01-25 18:56:17 -08001/*
2 * Copyright (C) 2010 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;
18
Dianne Hackborn28429032010-01-25 18:56:17 -080019import android.app.Activity;
Sudheer Shankaacb1a612016-11-10 15:30:14 -080020import android.app.ActivityManager;
Dianne Hackborn61daf832010-01-27 16:22:05 -080021import android.app.AlertDialog;
Jason Monk39b46742015-09-10 15:52:51 -040022import android.app.AppOpsManager;
Dianne Hackborn61daf832010-01-27 16:22:05 -080023import android.app.Dialog;
Dianne Hackborn4037c7f2010-02-26 17:26:55 -080024import android.app.admin.DeviceAdminInfo;
25import android.app.admin.DeviceAdminReceiver;
26import android.app.admin.DevicePolicyManager;
Dianne Hackborn28429032010-01-25 18:56:17 -080027import android.content.ComponentName;
28import android.content.Context;
Dianne Hackborn61daf832010-01-27 16:22:05 -080029import android.content.DialogInterface;
Dianne Hackborn39e64e72010-03-26 13:24:39 -070030import android.content.Intent;
Dianne Hackborn28429032010-01-25 18:56:17 -080031import android.content.pm.ActivityInfo;
Amith Yamasani080f8db2014-08-13 11:11:44 -070032import android.content.pm.ApplicationInfo;
33import android.content.pm.PackageInfo;
Dianne Hackborn28429032010-01-25 18:56:17 -080034import android.content.pm.PackageManager;
Amith Yamasani080f8db2014-08-13 11:11:44 -070035import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborn28429032010-01-25 18:56:17 -080036import android.content.pm.ResolveInfo;
Kenny Guy7a355592015-12-22 12:11:41 +000037import android.content.pm.UserInfo;
Dianne Hackborn28429032010-01-25 18:56:17 -080038import android.content.res.Resources;
Fyodor Kupolov1f432582015-09-18 18:22:24 -070039import android.os.Binder;
Dianne Hackborn28429032010-01-25 18:56:17 -080040import android.os.Bundle;
Dianne Hackborn61daf832010-01-27 16:22:05 -080041import android.os.Handler;
Suprabh Shukla05c8eb52017-05-22 15:20:06 -070042import android.os.IBinder;
Dianne Hackborn61daf832010-01-27 16:22:05 -080043import android.os.RemoteCallback;
Dianne Hackborn4f25e1d2011-03-02 22:39:49 -080044import android.os.RemoteException;
Amith Yamasanib8e0f602014-07-28 16:28:36 -070045import android.os.UserHandle;
Xiaohui Chenf9ee84d2015-10-21 11:25:35 -070046import android.os.UserManager;
Kenny Guy7a355592015-12-22 12:11:41 +000047import android.text.TextUtils;
Chris Palmer51794a02010-09-13 15:14:55 -070048import android.text.TextUtils.TruncateAt;
William Luh64e676a2013-11-22 15:42:40 -080049import android.util.EventLog;
Dianne Hackborn28429032010-01-25 18:56:17 -080050import android.util.Log;
Chris Palmer51794a02010-09-13 15:14:55 -070051import android.view.Display;
Dianne Hackborn28429032010-01-25 18:56:17 -080052import android.view.View;
53import android.view.ViewGroup;
Fyodor Kupolov1c8600b2015-05-29 11:17:32 -070054import android.view.ViewTreeObserver;
Chris Palmer51794a02010-09-13 15:14:55 -070055import android.view.WindowManager;
Dianne Hackborn28429032010-01-25 18:56:17 -080056import android.widget.AppSecurityPermissions;
Dianne Hackborn61daf832010-01-27 16:22:05 -080057import android.widget.Button;
Dianne Hackborn28429032010-01-25 18:56:17 -080058import android.widget.ImageView;
59import android.widget.TextView;
60
Fyodor Kupolov23289462017-01-13 15:14:24 -080061import com.android.internal.logging.nano.MetricsProto;
Fyodor Kupolov23289462017-01-13 15:14:24 -080062import com.android.settings.overlay.FeatureFactory;
Kenny Guy7a355592015-12-22 12:11:41 +000063import com.android.settings.users.UserDialogs;
Nicolas Prevot47354882017-01-24 14:29:59 +000064import com.android.settingslib.RestrictedLockUtils;
65import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
Tony Makee36bb92017-09-05 16:41:05 +010066
Jason Monk39b46742015-09-10 15:52:51 -040067import org.xmlpull.v1.XmlPullParserException;
68
Dianne Hackborn28429032010-01-25 18:56:17 -080069import java.io.IOException;
70import java.util.ArrayList;
Dianne Hackborn8274b672013-05-22 11:29:36 -070071import java.util.List;
Dianne Hackborn28429032010-01-25 18:56:17 -080072
73public class DeviceAdminAdd extends Activity {
74 static final String TAG = "DeviceAdminAdd";
William Luh64e676a2013-11-22 15:42:40 -080075
Dianne Hackborn61daf832010-01-27 16:22:05 -080076 static final int DIALOG_WARNING = 1;
Chris Palmer51794a02010-09-13 15:14:55 -070077
78 private static final int MAX_ADD_MSG_LINES_PORTRAIT = 5;
79 private static final int MAX_ADD_MSG_LINES_LANDSCAPE = 2;
80 private static final int MAX_ADD_MSG_LINES = 15;
William Luh64e676a2013-11-22 15:42:40 -080081
Suprabh Shukla02a06ef2016-01-27 13:00:10 -080082 /**
83 * Optional key to map to the package name of the Device Admin.
84 * Currently only used when uninstalling an active device admin.
85 */
86 public static final String EXTRA_DEVICE_ADMIN_PACKAGE_NAME =
87 "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
88
Sudheer Shanka17cbc992016-04-11 23:09:08 -070089 public static final String EXTRA_CALLED_FROM_SUPPORT_DIALOG =
90 "android.app.extra.CALLED_FROM_SUPPORT_DIALOG";
91
Suprabh Shukla05c8eb52017-05-22 15:20:06 -070092 private final IBinder mToken = new Binder();
Dianne Hackborn61daf832010-01-27 16:22:05 -080093 Handler mHandler;
William Luh64e676a2013-11-22 15:42:40 -080094
Dianne Hackborn28429032010-01-25 18:56:17 -080095 DevicePolicyManager mDPM;
Dianne Hackbornb763e342014-07-22 16:23:36 -070096 AppOpsManager mAppOps;
Dianne Hackborn28429032010-01-25 18:56:17 -080097 DeviceAdminInfo mDeviceAdmin;
Dianne Hackbornb885afe2010-01-26 18:03:42 -080098 CharSequence mAddMsgText;
Amith Yamasanib8e0f602014-07-28 16:28:36 -070099 String mProfileOwnerName;
William Luh64e676a2013-11-22 15:42:40 -0800100
Dianne Hackborn61daf832010-01-27 16:22:05 -0800101 ImageView mAdminIcon;
102 TextView mAdminName;
103 TextView mAdminDescription;
Dianne Hackbornb885afe2010-01-26 18:03:42 -0800104 TextView mAddMsg;
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700105 TextView mProfileOwnerWarning;
Amith Yamasania1d01842011-01-24 16:02:11 -0800106 ImageView mAddMsgExpander;
Chris Palmer51794a02010-09-13 15:14:55 -0700107 boolean mAddMsgEllipsized = true;
Dianne Hackborn61daf832010-01-27 16:22:05 -0800108 TextView mAdminWarning;
Kenny Guy7a355592015-12-22 12:11:41 +0000109 TextView mSupportMessage;
Dianne Hackborn28429032010-01-25 18:56:17 -0800110 ViewGroup mAdminPolicies;
Dianne Hackborn61daf832010-01-27 16:22:05 -0800111 Button mActionButton;
Makoto Onukic5488482016-01-22 15:21:56 -0800112 Button mUninstallButton;
Dianne Hackborn97de6bc2010-03-03 17:18:13 -0800113 Button mCancelButton;
William Luh64e676a2013-11-22 15:42:40 -0800114
Suprabh Shukla02a06ef2016-01-27 13:00:10 -0800115 boolean mUninstalling = false;
Dianne Hackborn61daf832010-01-27 16:22:05 -0800116 boolean mAdding;
Andy Stadler5cc0e412010-12-08 15:57:18 -0800117 boolean mRefreshing;
Dianne Hackbornb763e342014-07-22 16:23:36 -0700118 boolean mWaitingForRemoveMsg;
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700119 boolean mAddingProfileOwner;
Fyodor Kupolov7dc56bd2015-02-24 09:26:53 -0800120 boolean mAdminPoliciesInitialized;
William Luh64e676a2013-11-22 15:42:40 -0800121
Sudheer Shanka17cbc992016-04-11 23:09:08 -0700122 boolean mIsCalledFromSupportDialog = false;
123
Dianne Hackborn28429032010-01-25 18:56:17 -0800124 @Override
125 protected void onCreate(Bundle icicle) {
126 super.onCreate(icicle);
127
Dianne Hackborn61daf832010-01-27 16:22:05 -0800128 mHandler = new Handler(getMainLooper());
William Luh64e676a2013-11-22 15:42:40 -0800129
Dianne Hackborn28429032010-01-25 18:56:17 -0800130 mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
Dianne Hackbornb763e342014-07-22 16:23:36 -0700131 mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
Amith Yamasani080f8db2014-08-13 11:11:44 -0700132 PackageManager packageManager = getPackageManager();
Dianne Hackborn28429032010-01-25 18:56:17 -0800133
Dianne Hackborn39e64e72010-03-26 13:24:39 -0700134 if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Andy Stadler5cc0e412010-12-08 15:57:18 -0800135 Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
Dianne Hackborn39e64e72010-03-26 13:24:39 -0700136 finish();
137 return;
138 }
William Luh64e676a2013-11-22 15:42:40 -0800139
Sudheer Shanka17cbc992016-04-11 23:09:08 -0700140 mIsCalledFromSupportDialog = getIntent().getBooleanExtra(
141 EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
Suprabh Shukla02a06ef2016-01-27 13:00:10 -0800142
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700143 String action = getIntent().getAction();
144 ComponentName who = (ComponentName)getIntent().getParcelableExtra(
Dianne Hackborn28429032010-01-25 18:56:17 -0800145 DevicePolicyManager.EXTRA_DEVICE_ADMIN);
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700146 if (who == null) {
Suprabh Shukla02a06ef2016-01-27 13:00:10 -0800147 String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
148 for (ComponentName component : mDPM.getActiveAdmins()) {
149 if (component.getPackageName().equals(packageName)) {
150 who = component;
151 mUninstalling = true;
152 break;
153 }
154 }
155 if (who == null) {
156 Log.w(TAG, "No component specified in " + action);
157 finish();
158 return;
159 }
Dianne Hackborn28429032010-01-25 18:56:17 -0800160 }
Dianne Hackborn8274b672013-05-22 11:29:36 -0700161
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700162 if (action != null && action.equals(DevicePolicyManager.ACTION_SET_PROFILE_OWNER)) {
Amith Yamasani080f8db2014-08-13 11:11:44 -0700163 setResult(RESULT_CANCELED);
164 setFinishOnTouchOutside(true);
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700165 mAddingProfileOwner = true;
166 mProfileOwnerName =
167 getIntent().getStringExtra(DevicePolicyManager.EXTRA_PROFILE_OWNER_NAME);
168 String callingPackage = getCallingPackage();
169 if (callingPackage == null || !callingPackage.equals(who.getPackageName())) {
170 Log.e(TAG, "Unknown or incorrect caller");
171 finish();
172 return;
173 }
Amith Yamasani080f8db2014-08-13 11:11:44 -0700174 try {
175 PackageInfo packageInfo = packageManager.getPackageInfo(callingPackage, 0);
176 if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
177 Log.e(TAG, "Cannot set a non-system app as a profile owner");
178 finish();
179 return;
180 }
181 } catch (NameNotFoundException nnfe) {
182 Log.e(TAG, "Cannot find the package " + callingPackage);
183 finish();
184 return;
185 }
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700186 }
187
Dianne Hackborn28429032010-01-25 18:56:17 -0800188 ActivityInfo ai;
189 try {
Amith Yamasani080f8db2014-08-13 11:11:44 -0700190 ai = packageManager.getReceiverInfo(who, PackageManager.GET_META_DATA);
Dianne Hackborn28429032010-01-25 18:56:17 -0800191 } catch (PackageManager.NameNotFoundException e) {
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700192 Log.w(TAG, "Unable to retrieve device policy " + who, e);
Dianne Hackborn28429032010-01-25 18:56:17 -0800193 finish();
194 return;
195 }
Dianne Hackborn8274b672013-05-22 11:29:36 -0700196
Alex Klyubin29de9d52013-06-06 14:56:24 -0700197 // When activating, make sure the given component name is actually a valid device admin.
198 // No need to check this when deactivating, because it is safe to deactivate an active
199 // invalid device admin.
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700200 if (!mDPM.isAdminActive(who)) {
Amith Yamasani080f8db2014-08-13 11:11:44 -0700201 List<ResolveInfo> avail = packageManager.queryBroadcastReceivers(
Alex Klyubin29de9d52013-06-06 14:56:24 -0700202 new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
Alex Klyubin681b21f2013-06-06 15:45:23 -0700203 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
Alex Klyubin29de9d52013-06-06 14:56:24 -0700204 int count = avail == null ? 0 : avail.size();
205 boolean found = false;
206 for (int i=0; i<count; i++) {
207 ResolveInfo ri = avail.get(i);
208 if (ai.packageName.equals(ri.activityInfo.packageName)
209 && ai.name.equals(ri.activityInfo.name)) {
210 try {
211 // We didn't retrieve the meta data for all possible matches, so
212 // need to use the activity info of this specific one that was retrieved.
213 ri.activityInfo = ai;
214 DeviceAdminInfo dpi = new DeviceAdminInfo(this, ri);
215 found = true;
216 } catch (XmlPullParserException e) {
217 Log.w(TAG, "Bad " + ri.activityInfo, e);
218 } catch (IOException e) {
219 Log.w(TAG, "Bad " + ri.activityInfo, e);
220 }
221 break;
Dianne Hackborn8274b672013-05-22 11:29:36 -0700222 }
Dianne Hackborn8274b672013-05-22 11:29:36 -0700223 }
Alex Klyubin29de9d52013-06-06 14:56:24 -0700224 if (!found) {
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700225 Log.w(TAG, "Request to add invalid device admin: " + who);
Alex Klyubin29de9d52013-06-06 14:56:24 -0700226 finish();
227 return;
228 }
Dianne Hackborn8274b672013-05-22 11:29:36 -0700229 }
230
Dianne Hackborn28429032010-01-25 18:56:17 -0800231 ResolveInfo ri = new ResolveInfo();
232 ri.activityInfo = ai;
233 try {
Andy Stadler5cc0e412010-12-08 15:57:18 -0800234 mDeviceAdmin = new DeviceAdminInfo(this, ri);
Dianne Hackborn28429032010-01-25 18:56:17 -0800235 } catch (XmlPullParserException e) {
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700236 Log.w(TAG, "Unable to retrieve device policy " + who, e);
Dianne Hackborn28429032010-01-25 18:56:17 -0800237 finish();
238 return;
239 } catch (IOException e) {
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700240 Log.w(TAG, "Unable to retrieve device policy " + who, e);
Dianne Hackborn28429032010-01-25 18:56:17 -0800241 finish();
242 return;
243 }
William Luh64e676a2013-11-22 15:42:40 -0800244
Andy Stadler5cc0e412010-12-08 15:57:18 -0800245 // This admin already exists, an we have two options at this point. If new policy
246 // bits are set, show the user the new list. If nothing has changed, simply return
247 // "OK" immediately.
248 if (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN.equals(getIntent().getAction())) {
249 mRefreshing = false;
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700250 if (mDPM.isAdminActive(who)) {
Makoto Onukid1418562016-04-13 16:40:37 -0700251 if (mDPM.isRemovingAdmin(who, android.os.Process.myUserHandle().getIdentifier())) {
252 Log.w(TAG, "Requested admin is already being removed: " + who);
253 finish();
254 return;
255 }
256
Andy Stadler5cc0e412010-12-08 15:57:18 -0800257 ArrayList<DeviceAdminInfo.PolicyInfo> newPolicies = mDeviceAdmin.getUsedPolicies();
258 for (int i = 0; i < newPolicies.size(); i++) {
259 DeviceAdminInfo.PolicyInfo pi = newPolicies.get(i);
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700260 if (!mDPM.hasGrantedPolicy(who, pi.ident)) {
Andy Stadler5cc0e412010-12-08 15:57:18 -0800261 mRefreshing = true;
262 break;
263 }
264 }
265 if (!mRefreshing) {
266 // Nothing changed (or policies were removed) - return immediately
267 setResult(Activity.RESULT_OK);
268 finish();
269 return;
270 }
271 }
272 }
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700273
274 // If we're trying to add a profile owner and user setup hasn't completed yet, no
275 // need to prompt for permission. Just add and finish.
276 if (mAddingProfileOwner && !mDPM.hasUserSetupCompleted()) {
277 addAndFinish();
278 return;
279 }
280
Andy Stadler5cc0e412010-12-08 15:57:18 -0800281 mAddMsgText = getIntent().getCharSequenceExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION);
Amith Yamasania1d01842011-01-24 16:02:11 -0800282
Dianne Hackborn28429032010-01-25 18:56:17 -0800283 setContentView(R.layout.device_admin_add);
William Luh64e676a2013-11-22 15:42:40 -0800284
Dianne Hackborn61daf832010-01-27 16:22:05 -0800285 mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
286 mAdminName = (TextView)findViewById(R.id.admin_name);
287 mAdminDescription = (TextView)findViewById(R.id.admin_description);
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700288 mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
Chris Palmer51794a02010-09-13 15:14:55 -0700289
Dianne Hackbornb885afe2010-01-26 18:03:42 -0800290 mAddMsg = (TextView)findViewById(R.id.add_msg);
Amith Yamasania1d01842011-01-24 16:02:11 -0800291 mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
Fyodor Kupolov1c8600b2015-05-29 11:17:32 -0700292 final View.OnClickListener onClickListener = new View.OnClickListener() {
293 @Override
Chris Palmer51794a02010-09-13 15:14:55 -0700294 public void onClick(View v) {
Fyodor Kupolov1c8600b2015-05-29 11:17:32 -0700295 toggleMessageEllipsis(mAddMsg);
Chris Palmer51794a02010-09-13 15:14:55 -0700296 }
Fyodor Kupolov1c8600b2015-05-29 11:17:32 -0700297 };
298 mAddMsgExpander.setOnClickListener(onClickListener);
299 mAddMsg.setOnClickListener(onClickListener);
300
301 // Determine whether the message can be collapsed - getLineCount() gives the correct
302 // number of lines only after a layout pass.
303 mAddMsg.getViewTreeObserver().addOnGlobalLayoutListener(
304 new ViewTreeObserver.OnGlobalLayoutListener() {
305 @Override
306 public void onGlobalLayout() {
307 final int maxLines = getEllipsizedLines();
308 // hide the icon if number of visible lines does not exceed maxLines
309 boolean hideMsgExpander = mAddMsg.getLineCount() <= maxLines;
310 mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
311 if (hideMsgExpander) {
312 mAddMsg.setOnClickListener(null);
313 ((View)mAddMsgExpander.getParent()).invalidate();
314 }
315 mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
316 }
317 });
Chris Palmer51794a02010-09-13 15:14:55 -0700318
319 // toggleMessageEllipsis also handles initial layout:
320 toggleMessageEllipsis(mAddMsg);
321
Amith Yamasania1d01842011-01-24 16:02:11 -0800322 mAdminWarning = (TextView) findViewById(R.id.admin_warning);
323 mAdminPolicies = (ViewGroup) findViewById(R.id.admin_policies);
Kenny Guy7a355592015-12-22 12:11:41 +0000324 mSupportMessage = (TextView) findViewById(R.id.admin_support_message);
Makoto Onukic5488482016-01-22 15:21:56 -0800325
Amith Yamasania1d01842011-01-24 16:02:11 -0800326 mCancelButton = (Button) findViewById(R.id.cancel_button);
Stephan Huberdc333212015-01-23 09:49:57 +0100327 mCancelButton.setFilterTouchesWhenObscured(true);
Dianne Hackborn97de6bc2010-03-03 17:18:13 -0800328 mCancelButton.setOnClickListener(new View.OnClickListener() {
329 public void onClick(View v) {
William Luh64e676a2013-11-22 15:42:40 -0800330 EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
331 mDeviceAdmin.getActivityInfo().applicationInfo.uid);
Dianne Hackborn97de6bc2010-03-03 17:18:13 -0800332 finish();
333 }
334 });
Makoto Onukic5488482016-01-22 15:21:56 -0800335
336 mUninstallButton = (Button) findViewById(R.id.uninstall_button);
337 mUninstallButton.setFilterTouchesWhenObscured(true);
338 mUninstallButton.setOnClickListener(new View.OnClickListener() {
339 public void onClick(View v) {
340 EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_UNINSTALLED_BY_USER,
341 mDeviceAdmin.getActivityInfo().applicationInfo.uid);
Makoto Onukia31c7252016-02-10 16:21:18 -0800342 mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
343 finish();
Makoto Onukic5488482016-01-22 15:21:56 -0800344 }
345 });
346
Amith Yamasania1d01842011-01-24 16:02:11 -0800347 mActionButton = (Button) findViewById(R.id.action_button);
Nicolas Prevot47354882017-01-24 14:29:59 +0000348
349 final View restrictedAction = findViewById(R.id.restricted_action);
350 restrictedAction.setFilterTouchesWhenObscured(true);
351 restrictedAction.setOnClickListener(new View.OnClickListener() {
Dianne Hackborn28429032010-01-25 18:56:17 -0800352 public void onClick(View v) {
Suprabh Shukla05c8eb52017-05-22 15:20:06 -0700353 if (!mActionButton.isEnabled()) {
Tony Makee36bb92017-09-05 16:41:05 +0100354 showPolicyTransparencyDialogIfRequired();
Suprabh Shukla05c8eb52017-05-22 15:20:06 -0700355 return;
356 }
Dianne Hackborn61daf832010-01-27 16:22:05 -0800357 if (mAdding) {
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700358 addAndFinish();
Kenny Guy7a355592015-12-22 12:11:41 +0000359 } else if (isManagedProfile(mDeviceAdmin)
360 && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
361 final int userId = UserHandle.myUserId();
362 UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
363 new DialogInterface.OnClickListener() {
364 @Override
365 public void onClick(DialogInterface dialog, int which) {
366 UserManager um = UserManager.get(DeviceAdminAdd.this);
367 um.removeUser(userId);
368 finish();
369 }
370 }
Tony Makee36bb92017-09-05 16:41:05 +0100371 ).show();
Suprabh Shukla02a06ef2016-01-27 13:00:10 -0800372 } else if (mUninstalling) {
373 mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
374 finish();
Dianne Hackbornb763e342014-07-22 16:23:36 -0700375 } else if (!mWaitingForRemoveMsg) {
Dianne Hackborn4f25e1d2011-03-02 22:39:49 -0800376 try {
377 // Don't allow the admin to put a dialog up in front
378 // of us while we interact with the user.
Sudheer Shankaacb1a612016-11-10 15:30:14 -0800379 ActivityManager.getService().stopAppSwitches();
Dianne Hackborn4f25e1d2011-03-02 22:39:49 -0800380 } catch (RemoteException e) {
381 }
Dianne Hackbornb763e342014-07-22 16:23:36 -0700382 mWaitingForRemoveMsg = true;
Andrew Stadler4df6edb2010-02-05 01:00:13 -0800383 mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
Svet Ganovc7f02872015-12-01 19:57:33 -0800384 new RemoteCallback(new RemoteCallback.OnResultListener() {
385 @Override
386 public void onResult(Bundle result) {
387 CharSequence msg = result != null
388 ? result.getCharSequence(
Dianne Hackborn54355112010-02-16 20:40:42 -0800389 DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
Svet Ganovc7f02872015-12-01 19:57:33 -0800390 : null;
391 continueRemoveAction(msg);
392 }
393 }, mHandler));
Dianne Hackbornb763e342014-07-22 16:23:36 -0700394 // Don't want to wait too long.
395 getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
396 @Override public void run() {
397 continueRemoveAction(null);
398 }
399 }, 2*1000);
Andrew Stadler4df6edb2010-02-05 01:00:13 -0800400 }
Dianne Hackborn28429032010-01-25 18:56:17 -0800401 }
402 });
403 }
William Luh64e676a2013-11-22 15:42:40 -0800404
Tony Makee36bb92017-09-05 16:41:05 +0100405 /**
406 * Shows a dialog to explain why the button is disabled if required.
407 */
408 private void showPolicyTransparencyDialogIfRequired() {
409 if (isManagedProfile(mDeviceAdmin)
410 && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
411 if (hasBaseCantRemoveProfileRestriction()) {
412 // If DISALLOW_REMOVE_MANAGED_PROFILE is set by the system, there's no
413 // point showing a dialog saying it's disabled by an admin.
414 return;
415 }
416 EnforcedAdmin enforcedAdmin = getAdminEnforcingCantRemoveProfile();
417 if (enforcedAdmin != null) {
418 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
419 DeviceAdminAdd.this,
420 enforcedAdmin);
421 }
422 }
423 }
424
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700425 void addAndFinish() {
426 try {
Fyodor Kupolov23289462017-01-13 15:14:24 -0800427 logSpecialPermissionChange(true, mDeviceAdmin.getComponent().getPackageName());
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700428 mDPM.setActiveAdmin(mDeviceAdmin.getComponent(), mRefreshing);
429 EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_ACTIVATED_BY_USER,
430 mDeviceAdmin.getActivityInfo().applicationInfo.uid);
431 setResult(Activity.RESULT_OK);
432 } catch (RuntimeException e) {
433 // Something bad happened... could be that it was
434 // already set, though.
435 Log.w(TAG, "Exception trying to activate admin "
436 + mDeviceAdmin.getComponent(), e);
437 if (mDPM.isAdminActive(mDeviceAdmin.getComponent())) {
438 setResult(Activity.RESULT_OK);
439 }
440 }
441 if (mAddingProfileOwner) {
442 try {
443 mDPM.setProfileOwner(mDeviceAdmin.getComponent(),
444 mProfileOwnerName, UserHandle.myUserId());
445 } catch (RuntimeException re) {
446 setResult(Activity.RESULT_CANCELED);
447 }
448 }
449 finish();
450 }
451
Dianne Hackbornb763e342014-07-22 16:23:36 -0700452 void continueRemoveAction(CharSequence msg) {
453 if (!mWaitingForRemoveMsg) {
454 return;
455 }
456 mWaitingForRemoveMsg = false;
457 if (msg == null) {
458 try {
Sudheer Shankaacb1a612016-11-10 15:30:14 -0800459 ActivityManager.getService().resumeAppSwitches();
Dianne Hackbornb763e342014-07-22 16:23:36 -0700460 } catch (RemoteException e) {
461 }
Fyodor Kupolov23289462017-01-13 15:14:24 -0800462 logSpecialPermissionChange(false, mDeviceAdmin.getComponent().getPackageName());
Dianne Hackbornb763e342014-07-22 16:23:36 -0700463 mDPM.removeActiveAdmin(mDeviceAdmin.getComponent());
464 finish();
465 } else {
466 try {
467 // Continue preventing anything from coming in front.
Sudheer Shankaacb1a612016-11-10 15:30:14 -0800468 ActivityManager.getService().stopAppSwitches();
Dianne Hackbornb763e342014-07-22 16:23:36 -0700469 } catch (RemoteException e) {
470 }
471 Bundle args = new Bundle();
472 args.putCharSequence(
473 DeviceAdminReceiver.EXTRA_DISABLE_WARNING, msg);
474 showDialog(DIALOG_WARNING, args);
475 }
476 }
477
Fyodor Kupolov23289462017-01-13 15:14:24 -0800478 void logSpecialPermissionChange(boolean allow, String packageName) {
479 int logCategory = allow ? MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_ADMIN_ALLOW :
480 MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_ADMIN_DENY;
481 FeatureFactory.getFactory(this).getMetricsFeatureProvider().action(this, logCategory, packageName);
482 }
483
Dianne Hackborn28429032010-01-25 18:56:17 -0800484 @Override
485 protected void onResume() {
486 super.onResume();
Suprabh Shukla05c8eb52017-05-22 15:20:06 -0700487 mActionButton.setEnabled(true);
Dianne Hackborn28429032010-01-25 18:56:17 -0800488 updateInterface();
Suprabh Shukla05c8eb52017-05-22 15:20:06 -0700489 // As long as we are running, don't let anyone overlay stuff on top of the screen.
490 mAppOps.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, true, mToken);
491 mAppOps.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW, true, mToken);
492
Dianne Hackbornb763e342014-07-22 16:23:36 -0700493 }
494
495 @Override
496 protected void onPause() {
497 super.onPause();
Suprabh Shukla05c8eb52017-05-22 15:20:06 -0700498 // This just greys out the button. The actual listener is attached to R.id.restricted_action
499 mActionButton.setEnabled(false);
500 mAppOps.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, false, mToken);
501 mAppOps.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW, false, mToken);
Dianne Hackbornb763e342014-07-22 16:23:36 -0700502 try {
Sudheer Shankaacb1a612016-11-10 15:30:14 -0800503 ActivityManager.getService().resumeAppSwitches();
Dianne Hackbornb763e342014-07-22 16:23:36 -0700504 } catch (RemoteException e) {
505 }
Dianne Hackborn28429032010-01-25 18:56:17 -0800506 }
William Luh64e676a2013-11-22 15:42:40 -0800507
Dianne Hackborn61daf832010-01-27 16:22:05 -0800508 @Override
Sudheer Shanka17cbc992016-04-11 23:09:08 -0700509 protected void onUserLeaveHint() {
510 super.onUserLeaveHint();
511 // In case this is triggered from support dialog, finish this activity once the user leaves
512 // so that this won't appear as a background next time support dialog is triggered. This
513 // is because the support dialog activity and this belong to the same task and we can't
514 // start this in new activity since we need to know the calling package in this activity.
515 if (mIsCalledFromSupportDialog) {
516 finish();
517 }
518 }
519
520 @Override
Dianne Hackborn61daf832010-01-27 16:22:05 -0800521 protected Dialog onCreateDialog(int id, Bundle args) {
522 switch (id) {
523 case DIALOG_WARNING: {
Dianne Hackborn54355112010-02-16 20:40:42 -0800524 CharSequence msg = args.getCharSequence(DeviceAdminReceiver.EXTRA_DISABLE_WARNING);
Fyodor Kupolov7dc56bd2015-02-24 09:26:53 -0800525 AlertDialog.Builder builder = new AlertDialog.Builder(this);
Dianne Hackborn61daf832010-01-27 16:22:05 -0800526 builder.setMessage(msg);
527 builder.setPositiveButton(R.string.dlg_ok,
528 new DialogInterface.OnClickListener() {
529 public void onClick(DialogInterface dialog, int which) {
Dianne Hackbornb763e342014-07-22 16:23:36 -0700530 try {
Sudheer Shankaacb1a612016-11-10 15:30:14 -0800531 ActivityManager.getService().resumeAppSwitches();
Dianne Hackbornb763e342014-07-22 16:23:36 -0700532 } catch (RemoteException e) {
533 }
Dianne Hackborn61daf832010-01-27 16:22:05 -0800534 mDPM.removeActiveAdmin(mDeviceAdmin.getComponent());
535 finish();
536 }
537 });
538 builder.setNegativeButton(R.string.dlg_cancel, null);
539 return builder.create();
540 }
541 default:
542 return super.onCreateDialog(id, args);
William Luh64e676a2013-11-22 15:42:40 -0800543
Dianne Hackborn61daf832010-01-27 16:22:05 -0800544 }
545 }
William Luh64e676a2013-11-22 15:42:40 -0800546
Dianne Hackborn28429032010-01-25 18:56:17 -0800547 void updateInterface() {
Nicolas Prevot47354882017-01-24 14:29:59 +0000548 findViewById(R.id.restricted_icon).setVisibility(View.GONE);
Dianne Hackborn61daf832010-01-27 16:22:05 -0800549 mAdminIcon.setImageDrawable(mDeviceAdmin.loadIcon(getPackageManager()));
550 mAdminName.setText(mDeviceAdmin.loadLabel(getPackageManager()));
Dianne Hackborn28429032010-01-25 18:56:17 -0800551 try {
Dianne Hackborn61daf832010-01-27 16:22:05 -0800552 mAdminDescription.setText(
Dianne Hackborn28429032010-01-25 18:56:17 -0800553 mDeviceAdmin.loadDescription(getPackageManager()));
Dianne Hackborn61daf832010-01-27 16:22:05 -0800554 mAdminDescription.setVisibility(View.VISIBLE);
Dianne Hackborn28429032010-01-25 18:56:17 -0800555 } catch (Resources.NotFoundException e) {
Dianne Hackborn61daf832010-01-27 16:22:05 -0800556 mAdminDescription.setVisibility(View.GONE);
Dianne Hackbornb885afe2010-01-26 18:03:42 -0800557 }
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700558 if (mAddingProfileOwner) {
559 mProfileOwnerWarning.setVisibility(View.VISIBLE);
560 }
Dianne Hackbornb885afe2010-01-26 18:03:42 -0800561 if (mAddMsgText != null) {
562 mAddMsg.setText(mAddMsgText);
563 mAddMsg.setVisibility(View.VISIBLE);
564 } else {
565 mAddMsg.setVisibility(View.GONE);
Amith Yamasania1d01842011-01-24 16:02:11 -0800566 mAddMsgExpander.setVisibility(View.GONE);
Dianne Hackborn28429032010-01-25 18:56:17 -0800567 }
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700568 if (!mRefreshing && !mAddingProfileOwner
569 && mDPM.isAdminActive(mDeviceAdmin.getComponent())) {
Dianne Hackborn61daf832010-01-27 16:22:05 -0800570 mAdding = false;
Kenny Guy7a355592015-12-22 12:11:41 +0000571 final boolean isProfileOwner =
572 mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner());
573 final boolean isManagedProfile = isManagedProfile(mDeviceAdmin);
574 if (isProfileOwner && isManagedProfile) {
575 // Profile owner in a managed profile, user can remove profile to disable admin.
576 mAdminWarning.setText(R.string.admin_profile_owner_message);
577 mActionButton.setText(R.string.remove_managed_profile_label);
Nicolas Prevot47354882017-01-24 14:29:59 +0000578
579 final EnforcedAdmin admin = getAdminEnforcingCantRemoveProfile();
580 final boolean hasBaseRestriction = hasBaseCantRemoveProfileRestriction();
581 if (admin != null && !hasBaseRestriction) {
582 findViewById(R.id.restricted_icon).setVisibility(View.VISIBLE);
583 }
584 mActionButton.setEnabled(admin == null && !hasBaseRestriction);
Kenny Guy7a355592015-12-22 12:11:41 +0000585 } else if (isProfileOwner || mDeviceAdmin.getComponent().equals(
586 mDPM.getDeviceOwnerComponentOnCallingUser())) {
587 // Profile owner in a user or device owner, user can't disable admin.
588 if (isProfileOwner) {
589 // Show profile owner in a user description.
590 mAdminWarning.setText(R.string.admin_profile_owner_user_message);
591 } else {
592 // Show device owner description.
593 mAdminWarning.setText(R.string.admin_device_owner_message);
594 }
595 mActionButton.setText(R.string.remove_device_admin);
596 mActionButton.setEnabled(false);
597 } else {
598 addDeviceAdminPolicies(false /* showDescription */);
599 mAdminWarning.setText(getString(R.string.device_admin_status,
600 mDeviceAdmin.getActivityInfo().applicationInfo.loadLabel(
601 getPackageManager())));
602 setTitle(R.string.active_device_admin_msg);
Suprabh Shukla02a06ef2016-01-27 13:00:10 -0800603 if (mUninstalling) {
604 mActionButton.setText(R.string.remove_and_uninstall_device_admin);
605 } else {
606 mActionButton.setText(R.string.remove_device_admin);
607 }
Kenny Guy7a355592015-12-22 12:11:41 +0000608 }
Sudheer Shanka4f0c7d32016-04-11 22:29:27 -0700609 CharSequence supportMessage = mDPM.getLongSupportMessageForUser(
Kenny Guy7a355592015-12-22 12:11:41 +0000610 mDeviceAdmin.getComponent(), UserHandle.myUserId());
611 if (!TextUtils.isEmpty(supportMessage)) {
612 mSupportMessage.setText(supportMessage);
613 mSupportMessage.setVisibility(View.VISIBLE);
614 } else {
615 mSupportMessage.setVisibility(View.GONE);
616 }
Dianne Hackborn61daf832010-01-27 16:22:05 -0800617 } else {
Fyodor Kupolov7dc56bd2015-02-24 09:26:53 -0800618 addDeviceAdminPolicies(true /* showDescription */);
Dianne Hackborn61daf832010-01-27 16:22:05 -0800619 mAdminWarning.setText(getString(R.string.device_admin_warning,
620 mDeviceAdmin.getActivityInfo().applicationInfo.loadLabel(getPackageManager())));
Amith Yamasanib8e0f602014-07-28 16:28:36 -0700621 if (mAddingProfileOwner) {
622 setTitle(getText(R.string.profile_owner_add_title));
623 } else {
624 setTitle(getText(R.string.add_device_admin_msg));
625 }
Dianne Hackborn61daf832010-01-27 16:22:05 -0800626 mActionButton.setText(getText(R.string.add_device_admin));
Makoto Onukic5488482016-01-22 15:21:56 -0800627 if (isAdminUninstallable()) {
628 mUninstallButton.setVisibility(View.VISIBLE);
629 }
Kenny Guy7a355592015-12-22 12:11:41 +0000630 mSupportMessage.setVisibility(View.GONE);
Dianne Hackborn61daf832010-01-27 16:22:05 -0800631 mAdding = true;
632 }
Dianne Hackborn28429032010-01-25 18:56:17 -0800633 }
Chris Palmer51794a02010-09-13 15:14:55 -0700634
Nicolas Prevot47354882017-01-24 14:29:59 +0000635 private EnforcedAdmin getAdminEnforcingCantRemoveProfile() {
636 // Removing a managed profile is disallowed if DISALLOW_REMOVE_MANAGED_PROFILE
637 // is set in the parent rather than the user itself.
638 return RestrictedLockUtils.checkIfRestrictionEnforced(this,
639 UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, getParentUserId());
640 }
641
642 private boolean hasBaseCantRemoveProfileRestriction() {
643 return RestrictedLockUtils.hasBaseUserRestriction(this,
644 UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, getParentUserId());
645 }
646
647 private int getParentUserId() {
648 return UserManager.get(this).getProfileParent(UserHandle.myUserId()).id;
649 }
650
Fyodor Kupolov7dc56bd2015-02-24 09:26:53 -0800651 private void addDeviceAdminPolicies(boolean showDescription) {
652 if (!mAdminPoliciesInitialized) {
Xiaohui Chenf9ee84d2015-10-21 11:25:35 -0700653 boolean isAdminUser = UserManager.get(this).isAdminUser();
Fyodor Kupolov7dc56bd2015-02-24 09:26:53 -0800654 for (DeviceAdminInfo.PolicyInfo pi : mDeviceAdmin.getUsedPolicies()) {
Xiaohui Chenf9ee84d2015-10-21 11:25:35 -0700655 int descriptionId = isAdminUser ? pi.description : pi.descriptionForSecondaryUsers;
656 int labelId = isAdminUser ? pi.label : pi.labelForSecondaryUsers;
Fyodor Kupolov7dc56bd2015-02-24 09:26:53 -0800657 View view = AppSecurityPermissions.getPermissionItemView(this, getText(labelId),
658 showDescription ? getText(descriptionId) : "", true);
659 mAdminPolicies.addView(view);
660 }
661 mAdminPoliciesInitialized = true;
662 }
663 }
Chris Palmer51794a02010-09-13 15:14:55 -0700664
665 void toggleMessageEllipsis(View v) {
666 TextView tv = (TextView) v;
667
668 mAddMsgEllipsized = ! mAddMsgEllipsized;
669 tv.setEllipsize(mAddMsgEllipsized ? TruncateAt.END : null);
670 tv.setMaxLines(mAddMsgEllipsized ? getEllipsizedLines() : MAX_ADD_MSG_LINES);
671
Amith Yamasania1d01842011-01-24 16:02:11 -0800672 mAddMsgExpander.setImageResource(mAddMsgEllipsized ?
Chris Palmer51794a02010-09-13 15:14:55 -0700673 com.android.internal.R.drawable.expander_ic_minimized :
674 com.android.internal.R.drawable.expander_ic_maximized);
675 }
676
677 int getEllipsizedLines() {
678 Display d = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
679 .getDefaultDisplay();
680
681 return d.getHeight() > d.getWidth() ?
682 MAX_ADD_MSG_LINES_PORTRAIT : MAX_ADD_MSG_LINES_LANDSCAPE;
683 }
684
Kenny Guy7a355592015-12-22 12:11:41 +0000685 /**
686 * @return true if adminInfo is running in a managed profile.
687 */
688 private boolean isManagedProfile(DeviceAdminInfo adminInfo) {
689 UserManager um = UserManager.get(this);
690 UserInfo info = um.getUserInfo(
691 UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid));
692 return info != null ? info.isManagedProfile() : false;
693 }
Makoto Onukic5488482016-01-22 15:21:56 -0800694
695 private boolean isAdminUninstallable() {
696 // System apps can't be uninstalled.
697 return !mDeviceAdmin.getActivityInfo().applicationInfo.isSystemApp();
698 }
Dianne Hackborn28429032010-01-25 18:56:17 -0800699}