Home | History | Annotate | Download | only in managedprovisioning
      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
     88         protected Void doInBackground(Intent ... intents) {
     89             initialize(intents[0]);
     90             startManagedProfileProvisioning();
     91             return null;
     92         }
     93     }
     94 
     95     @Override
     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
    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 
    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      */
    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      */
    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      */
    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 
    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      */
    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 
    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 
    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 
    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      */
    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 
    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      */
    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
    349     public IBinder onBind(Intent intent) {
    350         return null;
    351     }
    352 
    353     @Override
    354     public void onDestroy() {
    355         ProvisionLogger.logd("ManagedProvisioningService  ONDESTROY");
    356     }
    357 }
    358