1 /* 2 * Copyright 2014, 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.managedprovisioning; 18 19 import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE; 20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME; 22 import static android.Manifest.permission.BIND_DEVICE_ADMIN; 23 24 import android.app.Activity; 25 import android.app.ActivityManagerNative; 26 import android.app.IActivityManager; 27 import android.app.Service; 28 import android.app.admin.DevicePolicyManager; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.pm.ActivityInfo; 35 import android.content.pm.IPackageManager; 36 import android.content.pm.PackageInfo; 37 import android.content.pm.PackageManager; 38 import android.content.pm.PackageManager.NameNotFoundException; 39 import android.content.pm.UserInfo; 40 import android.os.AsyncTask; 41 import android.os.Parcelable; 42 import android.os.PersistableBundle; 43 import android.os.IBinder; 44 import android.os.Process; 45 import android.os.RemoteException; 46 import android.os.ServiceManager; 47 import android.os.UserHandle; 48 import android.os.UserManager; 49 import android.provider.MediaStore; 50 import android.provider.Settings; 51 import android.support.v4.content.LocalBroadcastManager; 52 import android.text.TextUtils; 53 54 import com.android.managedprovisioning.CrossProfileIntentFiltersHelper; 55 import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask; 56 57 /** 58 * Service that runs the managed provisioning. 59 * 60 * <p>This service is started from and sends updates to the {@link ManagedProvisioningActivity}, 61 * which contains the provisioning UI. 62 */ 63 public class ManagedProvisioningService extends Service { 64 65 // Intent actions for communication with DeviceOwnerProvisioningService. 66 public static final String ACTION_PROVISIONING_SUCCESS = 67 "com.android.managedprovisioning.provisioning_success"; 68 public static final String ACTION_PROVISIONING_ERROR = 69 "com.android.managedprovisioning.error"; 70 public static final String EXTRA_LOG_MESSAGE_KEY = "ProvisioingErrorLogMessage"; 71 72 private String mMdmPackageName; 73 private ComponentName mActiveAdminComponentName; 74 75 // PersistableBundle extra received in starting intent. 76 // Should be passed through to device management application when provisioning is complete. 77 private PersistableBundle mAdminExtrasBundle; 78 79 private IPackageManager mIpm; 80 private UserInfo mManagedProfileUserInfo; 81 private UserManager mUserManager; 82 83 private int mStartIdProvisioning; 84 private AsyncTask<Intent, Object, Void> runnerTask; 85 86 private class RunnerTask extends AsyncTask<Intent, Object, Void> { 87 @Override doInBackground(Intent .... intents)88 protected Void doInBackground(Intent ... intents) { 89 initialize(intents[0]); 90 startManagedProfileProvisioning(); 91 return null; 92 } 93 } 94 95 @Override onCreate()96 public void onCreate() { 97 super.onCreate(); 98 99 ProvisionLogger.logd("Managed provisioning service ONCREATE"); 100 101 mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 102 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); 103 104 runnerTask = new RunnerTask(); 105 } 106 107 @Override onStartCommand(final Intent intent, int flags, int startId)108 public int onStartCommand(final Intent intent, int flags, int startId) { 109 110 ProvisionLogger.logd("Starting managed provisioning service"); 111 try { 112 runnerTask.execute(intent); 113 } catch (IllegalStateException ex) { 114 ProvisionLogger.logd("ManagedProvisioningService: Provisioning already in progress, " 115 + "second provisioning intent not being processed"); 116 } 117 return START_NOT_STICKY; 118 } 119 initialize(Intent intent)120 private void initialize(Intent intent) { 121 mMdmPackageName = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME); 122 123 // Cast is guaranteed by check in Activity. 124 mAdminExtrasBundle = (PersistableBundle) intent.getParcelableExtra( 125 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE); 126 127 mActiveAdminComponentName = getAdminReceiverComponent(mMdmPackageName); 128 } 129 130 /** 131 * Find the Device admin receiver component from the manifest. 132 */ getAdminReceiverComponent(String packageName)133 private ComponentName getAdminReceiverComponent(String packageName) { 134 ComponentName adminReceiverComponent = null; 135 136 try { 137 PackageInfo pi = getPackageManager().getPackageInfo(packageName, 138 PackageManager.GET_RECEIVERS); 139 for (ActivityInfo ai : pi.receivers) { 140 if (!TextUtils.isEmpty(ai.permission) && 141 ai.permission.equals(BIND_DEVICE_ADMIN)) { 142 adminReceiverComponent = new ComponentName(packageName, ai.name); 143 144 } 145 } 146 } catch (NameNotFoundException e) { 147 error("Error: The provided mobile device management package does not define a device" 148 + "admin receiver component in its manifest."); 149 } 150 return adminReceiverComponent; 151 } 152 153 /** 154 * This is the core method of this class. It goes through every provisioning step. 155 */ startManagedProfileProvisioning()156 private void startManagedProfileProvisioning() { 157 158 ProvisionLogger.logd("Starting managed profile provisioning"); 159 160 // Work through the provisioning steps in their corresponding order 161 createProfile(getString(R.string.default_managed_profile_name)); 162 if (mManagedProfileUserInfo != null) { 163 new DeleteNonRequiredAppsTask(this, 164 mMdmPackageName, mManagedProfileUserInfo.id, 165 R.array.required_apps_managed_profile, 166 R.array.vendor_required_apps_managed_profile, 167 true /* We are creating a new profile */, 168 true /* Disable INSTALL_SHORTCUT listeners */, 169 new DeleteNonRequiredAppsTask.Callback() { 170 171 @Override 172 public void onSuccess() { 173 setUpProfileAndFinish(); 174 } 175 176 @Override 177 public void onError() { 178 error("Delete non required apps task failed."); 179 } 180 }).run(); 181 } 182 } 183 184 /** 185 * Called when the new profile is ready for provisioning (the profile is created and all the 186 * apps not needed have been deleted). 187 */ setUpProfileAndFinish()188 private void setUpProfileAndFinish() { 189 installMdmOnManagedProfile(); 190 setMdmAsActiveAdmin(); 191 setMdmAsManagedProfileOwner(); 192 startManagedProfile(); 193 CrossProfileIntentFiltersHelper.setFilters( 194 getPackageManager(), getUserId(), mManagedProfileUserInfo.id); 195 onProvisioningSuccess(mActiveAdminComponentName); 196 } 197 createProfile(String profileName)198 private void createProfile(String profileName) { 199 200 ProvisionLogger.logd("Creating managed profile with name " + profileName); 201 202 mManagedProfileUserInfo = mUserManager.createProfileForUser(profileName, 203 UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_DISABLED, 204 Process.myUserHandle().getIdentifier()); 205 206 if (mManagedProfileUserInfo == null) { 207 if (UserManager.getMaxSupportedUsers() == mUserManager.getUserCount()) { 208 error("Profile creation failed, maximum number of users reached."); 209 } else { 210 error("Couldn't create profile. Reason unknown."); 211 } 212 } 213 } 214 215 /** 216 * Initializes the user that underlies the managed profile. 217 * This is required so that the provisioning complete broadcast can be sent across to the 218 * profile and apps can run on it. 219 */ startManagedProfile()220 private void startManagedProfile() { 221 ProvisionLogger.logd("Starting user in background"); 222 IActivityManager iActivityManager = ActivityManagerNative.getDefault(); 223 try { 224 boolean success = iActivityManager.startUserInBackground(mManagedProfileUserInfo.id); 225 if (!success) { 226 error("Could not start user in background"); 227 } 228 } catch (RemoteException neverThrown) { 229 // Never thrown, as we are making local calls. 230 ProvisionLogger.loge("This should not happen.", neverThrown); 231 } 232 } 233 installMdmOnManagedProfile()234 private void installMdmOnManagedProfile() { 235 236 ProvisionLogger.logd("Installing mobile device management app " + mMdmPackageName + 237 " on managed profile"); 238 239 try { 240 int status = mIpm.installExistingPackageAsUser( 241 mMdmPackageName, mManagedProfileUserInfo.id); 242 switch (status) { 243 case PackageManager.INSTALL_SUCCEEDED: 244 return; 245 case PackageManager.INSTALL_FAILED_USER_RESTRICTED: 246 // Should not happen because we're not installing a restricted user 247 error("Could not install mobile device management app on managed " 248 + "profile because the user is restricted"); 249 case PackageManager.INSTALL_FAILED_INVALID_URI: 250 // Should not happen because we already checked 251 error("Could not install mobile device management app on managed " 252 + "profile because the package could not be found"); 253 default: 254 error("Could not install mobile device management app on managed " 255 + "profile. Unknown status: " + status); 256 } 257 } catch (RemoteException neverThrown) { 258 // Never thrown, as we are making local calls. 259 ProvisionLogger.loge("This should not happen.", neverThrown); 260 } 261 } 262 setMdmAsManagedProfileOwner()263 private void setMdmAsManagedProfileOwner() { 264 265 ProvisionLogger.logd("Setting package " + mMdmPackageName + " as managed profile owner."); 266 267 DevicePolicyManager dpm = 268 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 269 if (!dpm.setProfileOwner(mActiveAdminComponentName, mMdmPackageName, 270 mManagedProfileUserInfo.id)) { 271 ProvisionLogger.logw("Could not set profile owner."); 272 error("Could not set profile owner."); 273 } 274 } 275 setMdmAsActiveAdmin()276 private void setMdmAsActiveAdmin() { 277 278 ProvisionLogger.logd("Setting package " + mMdmPackageName + " as active admin."); 279 280 DevicePolicyManager dpm = 281 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 282 dpm.setActiveAdmin(mActiveAdminComponentName, true /* refreshing*/, 283 mManagedProfileUserInfo.id); 284 } 285 286 /** 287 * Notify the mdm that provisioning has completed. When the mdm has received the intent, stop 288 * the service and notify the {@link ManagedProvisioningActivity} so that it can finish itself. 289 * 290 * @param deviceAdminComponent The component of the mdm that will be notified. 291 */ onProvisioningSuccess(ComponentName deviceAdminComponent)292 private void onProvisioningSuccess(ComponentName deviceAdminComponent) { 293 Settings.Secure.putIntForUser(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 294 1 /* true- > setup complete */, mManagedProfileUserInfo.id); 295 296 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 297 UserHandle userHandle = userManager.getUserForSerialNumber( 298 mManagedProfileUserInfo.serialNumber); 299 300 Intent completeIntent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE); 301 completeIntent.setComponent(mActiveAdminComponentName); 302 completeIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 303 Intent.FLAG_RECEIVER_FOREGROUND); 304 if (mAdminExtrasBundle != null) { 305 completeIntent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, mAdminExtrasBundle); 306 } 307 308 // Use an ordered broadcast, so that we only finish when the mdm has received it. 309 // Avoids a lag in the transition between provisioning and the mdm. 310 BroadcastReceiver mdmReceivedSuccessReceiver = new BroadcastReceiver() { 311 @Override 312 public void onReceive(Context context, Intent intent) { 313 ProvisionLogger.logd("ACTION_PROFILE_PROVISIONING_COMPLETE broadcast received by" 314 + " mdm"); 315 Intent successIntent = new Intent(ACTION_PROVISIONING_SUCCESS); 316 LocalBroadcastManager.getInstance(ManagedProvisioningService.this) 317 .sendBroadcast(successIntent); 318 stopSelf(); 319 } 320 321 }; 322 sendOrderedBroadcastAsUser(completeIntent, userHandle, null, 323 mdmReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null); 324 325 ProvisionLogger.logd("Provisioning complete broadcast has been sent to user " 326 + userHandle.getIdentifier()); 327 } 328 error(String logMessage)329 private void error(String logMessage) { 330 Intent intent = new Intent(ACTION_PROVISIONING_ERROR); 331 intent.putExtra(EXTRA_LOG_MESSAGE_KEY, logMessage); 332 LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 333 cleanup(); 334 stopSelf(); 335 } 336 337 /** 338 * Performs cleanup of the device on failure. 339 */ cleanup()340 private void cleanup() { 341 // The only cleanup we need to do is remove the profile we created. 342 if (mManagedProfileUserInfo != null) { 343 ProvisionLogger.logd("Removing managed profile"); 344 mUserManager.removeUser(mManagedProfileUserInfo.id); 345 } 346 } 347 348 @Override onBind(Intent intent)349 public IBinder onBind(Intent intent) { 350 return null; 351 } 352 353 @Override onDestroy()354 public void onDestroy() { 355 ProvisionLogger.logd("ManagedProvisioningService ONDESTROY"); 356 } 357 } 358