1 /* 2 * Copyright (C) 2017 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 package com.android.phone.euicc; 17 18 import android.annotation.Nullable; 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.ActivityInfo; 23 import android.os.Bundle; 24 import android.provider.Settings; 25 import android.service.euicc.EuiccService; 26 import android.telephony.euicc.EuiccManager; 27 import android.util.Log; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.telephony.euicc.EuiccConnector; 31 32 /** Trampoline activity to forward eUICC intents from apps to the active UI implementation. */ 33 public class EuiccUiDispatcherActivity extends Activity { 34 private static final String TAG = "EuiccUiDispatcher"; 35 36 @Override onCreate(Bundle savedInstanceState)37 public void onCreate(Bundle savedInstanceState) { 38 super.onCreate(savedInstanceState); 39 try { 40 Intent euiccUiIntent = resolveEuiccUiIntent(); 41 if (euiccUiIntent == null) { 42 setResult(RESULT_CANCELED); 43 onDispatchFailure(); 44 return; 45 } 46 47 euiccUiIntent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); 48 startActivity(euiccUiIntent); 49 } finally { 50 // Since we're using Theme.NO_DISPLAY, we must always finish() at the end of onCreate(). 51 finish(); 52 } 53 } 54 55 @VisibleForTesting 56 @Nullable resolveEuiccUiIntent()57 Intent resolveEuiccUiIntent() { 58 EuiccManager euiccManager = (EuiccManager) getSystemService(Context.EUICC_SERVICE); 59 if (!euiccManager.isEnabled()) { 60 Log.w(TAG, "eUICC not enabled"); 61 return null; 62 } 63 64 Intent euiccUiIntent = getEuiccUiIntent(); 65 if (euiccUiIntent == null) { 66 Log.w(TAG, "Unable to handle intent"); 67 return null; 68 } 69 70 ActivityInfo activityInfo = findBestActivity(euiccUiIntent); 71 if (activityInfo == null) { 72 Log.w(TAG, "Could not resolve activity for intent: " + euiccUiIntent); 73 return null; 74 } 75 76 euiccUiIntent.setComponent(activityInfo.getComponentName()); 77 return euiccUiIntent; 78 } 79 80 /** Called when dispatch fails. May be overridden to perform some operation here. */ onDispatchFailure()81 protected void onDispatchFailure() { 82 } 83 84 /** 85 * Return an Intent to start the Euicc app's UI for the given intent, or null if given intent 86 * cannot be handled. 87 */ 88 @Nullable getEuiccUiIntent()89 protected Intent getEuiccUiIntent() { 90 String action = getIntent().getAction(); 91 92 Intent intent = new Intent(); 93 switch (action) { 94 case EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS: 95 intent.setAction(EuiccService.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS); 96 break; 97 case EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION: 98 if (isDeviceProvisioned()) { 99 Log.w(TAG, "Cannot perform eUICC provisioning once device is provisioned"); 100 return null; 101 } 102 intent.setAction(EuiccService.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION); 103 intent.putExtra( 104 EuiccManager.EXTRA_FORCE_PROVISION, 105 getIntent().getBooleanExtra(EuiccManager.EXTRA_FORCE_PROVISION, false)); 106 break; 107 default: 108 Log.w(TAG, "Unsupported action: " + action); 109 return null; 110 } 111 112 return intent; 113 } 114 115 @VisibleForTesting isDeviceProvisioned()116 boolean isDeviceProvisioned() { 117 return Settings.Global.getInt(getContentResolver(), 118 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 119 } 120 121 @VisibleForTesting 122 @Nullable findBestActivity(Intent euiccUiIntent)123 ActivityInfo findBestActivity(Intent euiccUiIntent) { 124 return EuiccConnector.findBestActivity(getPackageManager(), euiccUiIntent); 125 } 126 } 127