1 /*
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 
17 package com.android.tv.settings.deviceadmin;
18 
19 import android.app.Activity;
20 import android.app.admin.DeviceAdminInfo;
21 import android.app.admin.DeviceAdminReceiver;
22 import android.app.admin.DevicePolicyManager;
23 import android.app.settings.SettingsEnums;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.pm.ActivityInfo;
28 import android.content.pm.ApplicationInfo;
29 import android.content.pm.PackageInfo;
30 import android.content.pm.PackageManager;
31 import android.content.pm.PackageManager.NameNotFoundException;
32 import android.content.pm.ResolveInfo;
33 import android.os.Bundle;
34 import android.os.UserHandle;
35 import android.util.EventLog;
36 import android.util.Log;
37 
38 import org.xmlpull.v1.XmlPullParserException;
39 
40 import java.io.IOException;
41 import java.util.List;
42 
43 public class DeviceAdminAdd extends Activity {
44     static final String TAG = "DeviceAdminAdd";
45 
46     DevicePolicyManager mDPM;
47     DeviceAdminInfo mDeviceAdmin;
48     String mProfileOwnerName;
49 
50     boolean mRefreshing;
51     boolean mAddingProfileOwner;
52 
53     @Override
onCreate(Bundle icicle)54     protected void onCreate(Bundle icicle) {
55         super.onCreate(icicle);
56 
57         mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
58         PackageManager packageManager = getPackageManager();
59 
60         if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
61             Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
62             finish();
63             return;
64         }
65 
66         String action = getIntent().getAction();
67         ComponentName who = (ComponentName)getIntent().getParcelableExtra(
68                 DevicePolicyManager.EXTRA_DEVICE_ADMIN);
69         if (who == null) {
70             Log.w(TAG, "No component specified in " + action);
71             finish();
72             return;
73         }
74 
75         if (action != null && action.equals(DevicePolicyManager.ACTION_SET_PROFILE_OWNER)) {
76             setResult(RESULT_CANCELED);
77             setFinishOnTouchOutside(true);
78             mAddingProfileOwner = true;
79             mProfileOwnerName =
80                     getIntent().getStringExtra(DevicePolicyManager.EXTRA_PROFILE_OWNER_NAME);
81             String callingPackage = getCallingPackage();
82             if (callingPackage == null || !callingPackage.equals(who.getPackageName())) {
83                 Log.e(TAG, "Unknown or incorrect caller");
84                 finish();
85                 return;
86             }
87             try {
88                 PackageInfo packageInfo = packageManager.getPackageInfo(callingPackage, 0);
89                 if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
90                     Log.e(TAG, "Cannot set a non-system app as a profile owner");
91                     finish();
92                     return;
93                 }
94             } catch (NameNotFoundException nnfe) {
95                 Log.e(TAG, "Cannot find the package " + callingPackage);
96                 finish();
97                 return;
98             }
99         }
100 
101         ActivityInfo ai;
102         try {
103             ai = packageManager.getReceiverInfo(who, PackageManager.GET_META_DATA);
104         } catch (PackageManager.NameNotFoundException e) {
105             Log.w(TAG, "Unable to retrieve device policy " + who, e);
106             finish();
107             return;
108         }
109 
110         // When activating, make sure the given component name is actually a valid device admin.
111         // No need to check this when deactivating, because it is safe to deactivate an active
112         // invalid device admin.
113         if (!mDPM.isAdminActive(who)) {
114             List<ResolveInfo> avail = packageManager.queryBroadcastReceivers(
115                     new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
116                     PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
117             int count = avail == null ? 0 : avail.size();
118             boolean found = false;
119             for (int i=0; i<count; i++) {
120                 ResolveInfo ri = avail.get(i);
121                 if (ai.packageName.equals(ri.activityInfo.packageName)
122                         && ai.name.equals(ri.activityInfo.name)) {
123                     try {
124                         // We didn't retrieve the meta data for all possible matches, so
125                         // need to use the activity info of this specific one that was retrieved.
126                         ri.activityInfo = ai;
127                         DeviceAdminInfo dpi = new DeviceAdminInfo(this, ri);
128                         found = true;
129                     } catch (XmlPullParserException e) {
130                         Log.w(TAG, "Bad " + ri.activityInfo, e);
131                     } catch (IOException e) {
132                         Log.w(TAG, "Bad " + ri.activityInfo, e);
133                     }
134                     break;
135                 }
136             }
137             if (!found) {
138                 Log.w(TAG, "Request to add invalid device admin: " + who);
139                 finish();
140                 return;
141             }
142         }
143 
144         ResolveInfo ri = new ResolveInfo();
145         ri.activityInfo = ai;
146         try {
147             mDeviceAdmin = new DeviceAdminInfo(this, ri);
148         } catch (XmlPullParserException e) {
149             Log.w(TAG, "Unable to retrieve device policy " + who, e);
150             finish();
151             return;
152         } catch (IOException e) {
153             Log.w(TAG, "Unable to retrieve device policy " + who, e);
154             finish();
155             return;
156         }
157 
158         if (mAddingProfileOwner) {
159             // If we're trying to add a profile owner and user setup hasn't completed yet, no
160             // need to prompt for permission. Just add and finish
161             if (!mDPM.hasUserSetupCompleted()) {
162                 addAndFinish();
163                 return;
164             }
165 
166             // othewise, only the defined default supervision profile owner can be set after user
167             // setup.
168             final String supervisor = getString(
169                     com.android.internal.R.string.config_defaultSupervisionProfileOwnerComponent);
170             if (supervisor == null) {
171                 Log.w(TAG, "Unable to set profile owner post-setup, no default supervisor"
172                         + "profile owner defined");
173                 finish();
174                 return;
175             }
176 
177             final ComponentName supervisorComponent = ComponentName.unflattenFromString(
178                     supervisor);
179             if (who.compareTo(supervisorComponent) != 0) {
180                 Log.w(TAG, "Unable to set non-default profile owner post-setup " + who);
181                 finish();
182                 return;
183             } else {
184                 addAndFinish();
185             }
186         }
187 
188         // do not finish if ACTION_ADD_DEVICE_ADMIN, expected by some CTS tests
189         if (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN.equals(getIntent().getAction())) {
190             if (mDPM.isAdminActive(who)) {
191                 if (mDPM.isRemovingAdmin(who, android.os.Process.myUserHandle().getIdentifier())) {
192                     Log.w(TAG, "Requested admin is already being removed: " + who);
193                     finish();
194                     return;
195                 }
196             }
197         } else {
198             finish();
199         }
200     }
201 
addAndFinish()202     void addAndFinish() {
203         try {
204             logSpecialPermissionChange(true, mDeviceAdmin.getComponent().getPackageName());
205             mDPM.setActiveAdmin(mDeviceAdmin.getComponent(), mRefreshing);
206             EventLog.writeEvent(1234,
207                 mDeviceAdmin.getActivityInfo().applicationInfo.uid);
208 
209             setResult(Activity.RESULT_OK);
210         } catch (RuntimeException e) {
211             // Something bad happened...  could be that it was
212             // already set, though.
213             Log.w(TAG, "Exception trying to activate admin "
214                     + mDeviceAdmin.getComponent(), e);
215             if (mDPM.isAdminActive(mDeviceAdmin.getComponent())) {
216                 setResult(Activity.RESULT_OK);
217             }
218         }
219         if (mAddingProfileOwner) {
220             try {
221                 mDPM.setProfileOwner(mDeviceAdmin.getComponent(),
222                         mProfileOwnerName, UserHandle.myUserId());
223             } catch (RuntimeException re) {
224                 setResult(Activity.RESULT_CANCELED);
225             }
226         }
227         finish();
228     }
229 
230 
logSpecialPermissionChange(boolean allow, String packageName)231     void logSpecialPermissionChange(boolean allow, String packageName) {
232         int logCategory = allow ? SettingsEnums.APP_SPECIAL_PERMISSION_ADMIN_ALLOW :
233                 SettingsEnums.APP_SPECIAL_PERMISSION_ADMIN_DENY;
234     }
235 }
236