DeviceOwnerProvisioningService.java revision 3ebb7b0557876ee6d8b59367f48ae4300a168811
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 17package com.android.managedprovisioning; 18 19import android.app.AlarmManager; 20import android.app.Service; 21import android.content.ComponentName; 22import android.content.Context; 23import android.content.Intent; 24import android.os.Bundle; 25import android.os.IBinder; 26import android.os.UserHandle; 27import android.support.v4.content.LocalBroadcastManager; 28import android.text.TextUtils; 29 30import com.android.internal.app.LocalePicker; 31import com.android.managedprovisioning.task.AddWifiNetworkTask; 32import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask; 33import com.android.managedprovisioning.task.DownloadPackageTask; 34import com.android.managedprovisioning.task.InstallPackageTask; 35import com.android.managedprovisioning.task.SetDevicePolicyTask; 36 37import java.lang.Runnable; 38import java.util.Locale; 39 40/** 41 * This service does the work for the DeviceOwnerProvisioningActivity. 42 * Feedback is sent back to the activity via intents. 43 * 44 * <p> 45 * If the corresponding activity is killed and restarted, the service is 46 * called twice. The service will not start the provisioning flow a second time, but instead 47 * send a status update to the activity. 48 * </p> 49 */ 50public class DeviceOwnerProvisioningService extends Service { 51 /** 52 * Intent action to activate the CDMA phone connection by OTASP. 53 * This is not necessary for a GSM phone connection, which is activated automatically. 54 * String must agree with the constants in com.android.phone.InCallScreenShowActivation. 55 */ 56 private static final String ACTION_PERFORM_CDMA_PROVISIONING = 57 "com.android.phone.PERFORM_CDMA_PROVISIONING"; 58 59 // Intent actions and extras for communication from DeviceOwnerProvisioningService to Activity. 60 protected static final String EXTRA_PROVISIONING_PARAMS = 61 "ProvisioningParams"; 62 63 // Intent actions and extras for communication from DeviceOwnerProvisioningActivity to Service. 64 protected static final String ACTION_PROVISIONING_SUCCESS = 65 "com.android.managedprovisioning.provisioning_success"; 66 protected static final String ACTION_PROVISIONING_ERROR = 67 "com.android.managedprovisioning.error"; 68 protected static final String EXTRA_USER_VISIBLE_ERROR_ID_KEY = 69 "UserVisibleErrorMessage-Id"; 70 protected static final String ACTION_PROGRESS_UPDATE = 71 "com.android.managedprovisioning.progress_update"; 72 protected static final String EXTRA_PROGRESS_MESSAGE_ID_KEY = 73 "ProgressMessageId"; 74 protected static final String ACTION_REQUEST_WIFI_PICK = 75 "com.android.managedprovisioning.request_wifi_pick"; 76 77 // Indicates whether provisioning has started. 78 private boolean mProvisioningInFlight = false; 79 80 // MessageId of the last progress message. 81 private int mLastProgressMessage = -1; 82 83 // MessageId of the last error message. 84 private int mLastErrorMessage = -1; 85 86 // Indicates whether provisioning has finished succesfully (service waiting to stop). 87 private boolean mDone = false; 88 89 // Provisioning tasks. 90 private AddWifiNetworkTask mAddWifiNetworkTask; 91 private DownloadPackageTask mDownloadPackageTask; 92 private InstallPackageTask mInstallPackageTask; 93 private SetDevicePolicyTask mSetDevicePolicyTask; 94 private DeleteNonRequiredAppsTask mDeleteNonRequiredAppsTask; 95 96 private ProvisioningParams mParams; 97 98 @Override 99 public int onStartCommand(final Intent intent, int flags, int startId) { 100 ProvisionLogger.logd("Device owner provisioning service ONSTARTCOMMAND."); 101 102 synchronized (this) { // Make operations on mProvisioningInFlight atomic. 103 if (mProvisioningInFlight) { 104 ProvisionLogger.logd("Provisioning already in flight."); 105 106 sendProgressUpdateToActivity(); 107 108 // Send error message if currently in error state. 109 if (mLastErrorMessage >= 0) { 110 sendError(); 111 } 112 113 // Send success if provisioning was succesful. 114 if (mDone) { 115 onProvisioningSuccess(mParams.mDeviceAdminPackageName); 116 } 117 } else { 118 mProvisioningInFlight = true; 119 ProvisionLogger.logd("First start of the service."); 120 progressUpdate(R.string.progress_data_process); 121 122 // Load the ProvisioningParams (from message in Intent). 123 mParams = (ProvisioningParams) intent.getParcelableExtra(EXTRA_PROVISIONING_PARAMS); 124 125 // Do the work on a separate thread. 126 new Thread(new Runnable() { 127 public void run() { 128 initializeProvisioningEnvironment(mParams); 129 startDeviceOwnerProvisioning(mParams); 130 } 131 }).start(); 132 } 133 } 134 return START_NOT_STICKY; 135 } 136 137 /** 138 * This is the core method of this class. It goes through every provisioning step. 139 */ 140 private void startDeviceOwnerProvisioning(final ProvisioningParams params) { 141 ProvisionLogger.logd("Starting device owner provisioning"); 142 143 // Construct Tasks. Do not start them yet. 144 mAddWifiNetworkTask = new AddWifiNetworkTask(this, params.mWifiSsid, 145 params.mWifiHidden, params.mWifiSecurityType, params.mWifiPassword, 146 params.mWifiProxyHost, params.mWifiProxyPort, params.mWifiProxyBypassHosts, 147 params.mWifiPacUrl, new AddWifiNetworkTask.Callback() { 148 @Override 149 public void onSuccess() { 150 if (!TextUtils.isEmpty(params.mDeviceAdminPackageDownloadLocation)) { 151 // Download, install, set as device owner, delete apps. 152 progressUpdate(R.string.progress_download); 153 mDownloadPackageTask.run(); 154 } else { 155 // Device Admin will not be downloaded (but is already present): 156 // Just set as device owner, delete apps. 157 progressUpdate(R.string.progress_set_owner); 158 mSetDevicePolicyTask.run(); 159 } 160 } 161 162 @Override 163 public void onError(){ 164 error(R.string.device_owner_error_wifi); 165 } 166 }); 167 168 mDownloadPackageTask = new DownloadPackageTask(this, 169 params.mDeviceAdminPackageDownloadLocation, params.mDeviceAdminPackageChecksum, 170 params.mDeviceAdminPackageDownloadCookieHeader, new DownloadPackageTask.Callback() { 171 @Override 172 public void onSuccess() { 173 String downloadLocation = 174 mDownloadPackageTask.getDownloadedPackageLocation(); 175 progressUpdate(R.string.progress_install); 176 mInstallPackageTask.run(downloadLocation); 177 } 178 179 @Override 180 public void onError(int errorCode) { 181 switch(errorCode) { 182 case DownloadPackageTask.ERROR_HASH_MISMATCH: 183 error(R.string.device_owner_error_hash_mismatch); 184 break; 185 case DownloadPackageTask.ERROR_DOWNLOAD_FAILED: 186 error(R.string.device_owner_error_download_failed); 187 break; 188 default: 189 error(R.string.device_owner_error_general); 190 break; 191 } 192 } 193 }); 194 195 mInstallPackageTask = new InstallPackageTask(this, 196 params.mDeviceAdminPackageName, 197 new InstallPackageTask.Callback() { 198 @Override 199 public void onSuccess() { 200 progressUpdate(R.string.progress_set_owner); 201 mSetDevicePolicyTask.run(); 202 } 203 204 @Override 205 public void onError(int errorCode) { 206 switch(errorCode) { 207 case InstallPackageTask.ERROR_PACKAGE_INVALID: 208 error(R.string.device_owner_error_package_invalid); 209 break; 210 case InstallPackageTask.ERROR_INSTALLATION_FAILED: 211 error(R.string.device_owner_error_installation_failed); 212 break; 213 default: 214 error(R.string.device_owner_error_general); 215 break; 216 } 217 } 218 }); 219 220 mSetDevicePolicyTask = new SetDevicePolicyTask(this, 221 params.mDeviceAdminPackageName, 222 getResources().getString(R.string.default_owned_device_username), 223 new SetDevicePolicyTask.Callback() { 224 @Override 225 public void onSuccess() { 226 mDeleteNonRequiredAppsTask.run(); 227 } 228 229 @Override 230 public void onError(int errorCode) { 231 switch(errorCode) { 232 case SetDevicePolicyTask.ERROR_PACKAGE_NOT_INSTALLED: 233 error(R.string.device_owner_error_package_not_installed); 234 break; 235 case SetDevicePolicyTask.ERROR_NO_RECEIVER: 236 error(R.string.device_owner_error_package_invalid); 237 break; 238 default: 239 error(R.string.device_owner_error_general); 240 break; 241 } 242 } 243 }); 244 245 mDeleteNonRequiredAppsTask = new DeleteNonRequiredAppsTask( 246 this, params.mDeviceAdminPackageName, UserHandle.USER_OWNER, 247 R.array.required_apps_managed_device, R.array.vendor_required_apps_managed_device, 248 true /* Disable sharing via Nfc and Bluetooth */, 249 false /* Do not disable INSTALL_SHORTCUT listeners */, 250 new DeleteNonRequiredAppsTask.Callback() { 251 public void onSuccess() { 252 // Done with provisioning. Success. 253 onProvisioningSuccess(params.mDeviceAdminPackageName); 254 } 255 256 @Override 257 public void onError() { 258 error(R.string.device_owner_error_general); 259 }; 260 }); 261 262 // Start first task, which starts next task in its callback, etc. 263 startFirstTask(params); 264 } 265 266 private void startFirstTask(final ProvisioningParams params) { 267 if (!TextUtils.isEmpty(params.mWifiSsid)) { 268 269 // Connect to wifi. 270 progressUpdate(R.string.progress_connect_to_wifi); 271 mAddWifiNetworkTask.run(); 272 } else if (!TextUtils.isEmpty(params.mDeviceAdminPackageDownloadLocation)) { 273 274 // Download, install, set as device owner, delete apps. 275 progressUpdate(R.string.progress_download); 276 mDownloadPackageTask.run(); 277 } else { 278 279 // Device Admin will not be downloaded (but is already present): 280 // Just set as device owner, delete apps. 281 progressUpdate(R.string.progress_set_owner); 282 mSetDevicePolicyTask.run(); 283 } 284 } 285 286 private void error(int dialogMessage) { 287 mLastErrorMessage = dialogMessage; 288 sendError(); 289 // Wait for stopService() call from the activity. 290 } 291 292 private void sendError() { 293 ProvisionLogger.logd("Reporting Error: " + getResources().getString(mLastErrorMessage)); 294 Intent intent = new Intent(ACTION_PROVISIONING_ERROR); 295 intent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class); 296 intent.putExtra(EXTRA_USER_VISIBLE_ERROR_ID_KEY, mLastErrorMessage); 297 LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 298 } 299 300 private void progressUpdate(int progressMessage) { 301 ProvisionLogger.logd("Reporting progress update: " 302 + getResources().getString(progressMessage)); 303 mLastProgressMessage = progressMessage; 304 sendProgressUpdateToActivity(); 305 } 306 307 private void sendProgressUpdateToActivity() { 308 Intent intent = new Intent(ACTION_PROGRESS_UPDATE); 309 intent.putExtra(EXTRA_PROGRESS_MESSAGE_ID_KEY, mLastProgressMessage); 310 intent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class); 311 LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 312 } 313 314 private void onProvisioningSuccess(String deviceAdminPackage) { 315 ProvisionLogger.logv("Reporting success."); 316 mDone = true; 317 Intent successIntent = new Intent(ACTION_PROVISIONING_SUCCESS); 318 successIntent.putExtra(EXTRA_PROVISIONING_PARAMS, mParams); 319 successIntent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class); 320 LocalBroadcastManager.getInstance(this).sendBroadcast(successIntent); 321 // Wait for stopService() call from the activity. 322 } 323 324 private void initializeProvisioningEnvironment(ProvisioningParams params) { 325 setTimeAndTimezone(params.mTimeZone, params.mLocalTime); 326 setLocale(params.mLocale); 327 328 // Start CDMA activation to enable phone calls. 329 final Intent intent = new Intent(ACTION_PERFORM_CDMA_PROVISIONING); 330 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 331 ProvisionLogger.logv("Starting cdma activation activity"); 332 startActivity(intent); // Activity will be a Nop if not a CDMA device. 333 } 334 335 private void setTimeAndTimezone(String timeZone, long localTime) { 336 try { 337 final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 338 if (timeZone != null) { 339 ProvisionLogger.logd("Setting time zone to " + timeZone); 340 am.setTimeZone(timeZone); 341 } 342 if (localTime > 0) { 343 ProvisionLogger.logd("Setting time to " + localTime); 344 am.setTime(localTime); 345 } 346 } catch (Exception e) { 347 ProvisionLogger.loge("Alarm manager failed to set the system time/timezone."); 348 // Do not stop provisioning process, but ignore this error. 349 } 350 } 351 352 private void setLocale(Locale locale) { 353 if (locale == null || locale.equals(Locale.getDefault())) { 354 return; 355 } 356 try { 357 ProvisionLogger.logd("Setting locale to " + locale); 358 // If locale is different from current locale this results in a configuration change, 359 // which will trigger the restarting of the activity. 360 LocalePicker.updateLocale(locale); 361 } catch (Exception e) { 362 ProvisionLogger.loge("Failed to set the system locale."); 363 // Do not stop provisioning process, but ignore this error. 364 } 365 } 366 367 @Override 368 public void onCreate () { 369 ProvisionLogger.logd("Device owner provisioning service ONCREATE."); 370 } 371 372 @Override 373 public void onDestroy () { 374 ProvisionLogger.logd("Device owner provisioning service ONDESTROY"); 375 if (mAddWifiNetworkTask != null) { 376 mAddWifiNetworkTask.cleanUp(); 377 } 378 if (mDownloadPackageTask != null) { 379 mDownloadPackageTask.cleanUp(); 380 } 381 } 382 383 @Override 384 public IBinder onBind(Intent intent) { 385 return null; 386 } 387} 388 389