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 17 package com.android.phone.testapps.imstestapp; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.os.Bundle; 22 import android.telephony.AccessNetworkConstants; 23 import android.telephony.SubscriptionManager; 24 import android.telephony.ims.ImsException; 25 import android.telephony.ims.ImsMmTelManager; 26 import android.telephony.ims.ImsReasonInfo; 27 import android.telephony.ims.RegistrationManager; 28 import android.telephony.ims.stub.ImsRegistrationImplBase; 29 import android.util.ArrayMap; 30 import android.util.Log; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.AdapterView; 35 import android.widget.ArrayAdapter; 36 import android.widget.Button; 37 import android.widget.EditText; 38 import android.widget.ListView; 39 import android.widget.Spinner; 40 import android.widget.TextView; 41 import android.widget.Toast; 42 43 import java.util.ArrayList; 44 import java.util.Map; 45 import java.util.Objects; 46 47 public class ImsRegistrationActivity extends Activity { 48 49 private static final String PREFIX_ITEM = "Registration Event: "; 50 private static final String PREFIX_VALUE = "Value: "; 51 52 53 private static class RegItem { 54 public String key; 55 public String value; 56 RegItem(String key, int value)57 RegItem(String key, int value) { 58 this.key = key; 59 this.value = String.valueOf(value); 60 } 61 RegItem(String key, String value)62 RegItem(String key, String value) { 63 this.key = key; 64 this.value = value; 65 } 66 67 @Override equals(Object o)68 public boolean equals(Object o) { 69 if (this == o) return true; 70 if (o == null || getClass() != o.getClass()) return false; 71 RegItem regItem = (RegItem) o; 72 return Objects.equals(key, regItem.key) 73 && Objects.equals(value, regItem.value); 74 } 75 76 @Override hashCode()77 public int hashCode() { 78 return Objects.hash(key, value); 79 } 80 } 81 82 private static class RegItemAdapter extends ArrayAdapter<RegItem> { RegItemAdapter(Context context, ArrayList<RegItem> regItems)83 RegItemAdapter(Context context, ArrayList<RegItem> regItems) { 84 super(context, 0, regItems); 85 } 86 87 @Override getView(int position, View convertView, ViewGroup parent)88 public View getView(int position, View convertView, ViewGroup parent) { 89 RegItem regItem = getItem(position); 90 91 if (convertView == null) { 92 convertView = LayoutInflater.from(getContext()).inflate(R.layout.config_item, 93 parent, false); 94 } 95 96 TextView textItem = (TextView) convertView.findViewById(R.id.configItem); 97 TextView textValue = (TextView) convertView.findViewById(R.id.configValue); 98 99 textItem.setText(PREFIX_ITEM + regItem.key); 100 textValue.setText(PREFIX_VALUE + regItem.value); 101 102 return convertView; 103 } 104 } 105 106 107 private final RegistrationManager.RegistrationCallback mRegistrationCallback = 108 new RegistrationManager.RegistrationCallback() { 109 110 @Override 111 public void onRegistered(int imsRadioTech) { 112 Log.i("ImsRegistrationActivity", "onRegistered: " + imsRadioTech); 113 mRegItems.add(new RegItem("Registered", REG_TECH_STRING.get(imsRadioTech))); 114 triggerAdapterChange(); 115 } 116 117 @Override 118 public void onRegistering(int imsRadioTech) { 119 Log.i("ImsRegistrationActivity", "onRegistering: " + imsRadioTech); 120 mRegItems.add(new RegItem("Registering", REG_TECH_STRING.get(imsRadioTech))); 121 triggerAdapterChange(); 122 } 123 124 @Override 125 public void onUnregistered(ImsReasonInfo info) { 126 Log.i("ImsRegistrationActivity", "onUnregistered: " + info); 127 mRegItems.add(new RegItem("Deregistered", info.toString())); 128 triggerAdapterChange(); 129 } 130 131 @Override 132 public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) { 133 mRegItems.add(new RegItem("TechnologyChangeFailed", REG_TECH_STRING.get(imsRadioTech) 134 + " reason: " + info)); 135 triggerAdapterChange(); 136 } 137 138 private void triggerAdapterChange() { 139 mRegItemAdapter.notifyDataSetChanged(); 140 } 141 }; 142 143 144 145 private int mSelectedRegTech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE; 146 147 private static final Map<String, Integer> REG_TECH = new ArrayMap<>(2); 148 static { 149 REG_TECH.put("LTE", ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 150 REG_TECH.put("IWLAN", ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN); 151 } 152 private static final Map<Integer, String> REG_TECH_STRING = new ArrayMap<>(2); 153 static { REG_TECH_STRING.put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, "NONE")154 REG_TECH_STRING.put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, "NONE"); REG_TECH_STRING.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, "WWAN")155 REG_TECH_STRING.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, "WWAN"); REG_TECH_STRING.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, "WLAN")156 REG_TECH_STRING.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, "WLAN"); 157 } 158 159 160 161 private ArrayList<RegItem> mRegItems = new ArrayList<>(); 162 RegItemAdapter mRegItemAdapter; 163 ListView mListView; 164 165 private View mDeregisteredReason; 166 private View mRegChangeFailedReason; 167 private ImsMmTelManager mImsManager; 168 169 @Override onCreate(Bundle savedInstanceState)170 protected void onCreate(Bundle savedInstanceState) { 171 super.onCreate(savedInstanceState); 172 173 setContentView(R.layout.activity_registration); 174 } 175 176 @Override onResume()177 protected void onResume() { 178 super.onResume(); 179 mRegItemAdapter = new RegItemAdapter(this, mRegItems); 180 mListView = (ListView) findViewById(R.id.reg_cb_list); 181 mListView.setAdapter(mRegItemAdapter); 182 try { 183 mImsManager = ImsMmTelManager.createForSubscriptionId( 184 SubscriptionManager.getDefaultVoiceSubscriptionId()); 185 mImsManager.registerImsRegistrationCallback(getMainExecutor(), mRegistrationCallback); 186 } catch (IllegalArgumentException | ImsException e) { 187 Log.w("ImsCallingActivity", "illegal subscription ID."); 188 } 189 190 //Set up registration tech spinner 191 Spinner regTechDropDown = findViewById(R.id.reg_tech_selector); 192 regTechDropDown.setAdapter(new ArrayAdapter<>(this, 193 android.R.layout.simple_spinner_dropdown_item, 194 REG_TECH.keySet().toArray(new String[REG_TECH.size()]))); 195 regTechDropDown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 196 197 @Override 198 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 199 onTechDropDownChanged((String) parent.getItemAtPosition(position)); 200 } 201 202 @Override 203 public void onNothingSelected(AdapterView<?> parent) { 204 // Don't change selection 205 } 206 }); 207 208 // Map buttons to onClick listeners 209 Button registeredButton = findViewById(R.id.reg_registered_button); 210 registeredButton.setOnClickListener((v)->onRegisteredClicked()); 211 Button registeringButton = findViewById(R.id.reg_registering_button); 212 registeringButton.setOnClickListener((v)->onRegisteringClicked()); 213 Button deregisteredButton = findViewById(R.id.reg_deregistered_button); 214 deregisteredButton.setOnClickListener((v)->onDeregisteredClicked()); 215 Button regChangeFailedButton = findViewById(R.id.reg_changefailed_button); 216 regChangeFailedButton.setOnClickListener((v)->onRegChangeFailedClicked()); 217 218 mDeregisteredReason = findViewById(R.id.deregistered_imsreasoninfo); 219 mRegChangeFailedReason = findViewById(R.id.regchangefail_imsreasoninfo); 220 } 221 222 @Override onPause()223 protected void onPause() { 224 super.onPause(); 225 mImsManager.unregisterImsRegistrationCallback(mRegistrationCallback); 226 mImsManager = null; 227 } 228 onRegisteredClicked()229 private void onRegisteredClicked() { 230 if (!isFrameworkConnected()) { 231 return; 232 } 233 TestImsRegistrationImpl.getInstance().onRegistered(mSelectedRegTech); 234 } 235 onRegisteringClicked()236 private void onRegisteringClicked() { 237 if (!isFrameworkConnected()) { 238 return; 239 } 240 TestImsRegistrationImpl.getInstance().onRegistering(mSelectedRegTech); 241 } 242 onDeregisteredClicked()243 private void onDeregisteredClicked() { 244 if (!isFrameworkConnected()) { 245 return; 246 } 247 TestImsRegistrationImpl.getInstance().onDeregistered(getReasonInfo(mDeregisteredReason)); 248 } 249 onRegChangeFailedClicked()250 private void onRegChangeFailedClicked() { 251 if (!isFrameworkConnected()) { 252 return; 253 } 254 TestImsRegistrationImpl.getInstance().onTechnologyChangeFailed(mSelectedRegTech, 255 getReasonInfo(mRegChangeFailedReason)); 256 } 257 onTechDropDownChanged(String item)258 private void onTechDropDownChanged(String item) { 259 mSelectedRegTech = REG_TECH.get(item); 260 } 261 getReasonInfo(View reasonView)262 private ImsReasonInfo getReasonInfo(View reasonView) { 263 EditText errorCodeText = reasonView.findViewById(R.id.imsreasoninfo_error); 264 EditText extraCodeText = reasonView.findViewById(R.id.imsreasoninfo_extra); 265 EditText messageText = reasonView.findViewById(R.id.imsreasoninfo_message); 266 267 int errorCode = ImsReasonInfo.CODE_UNSPECIFIED; 268 try { 269 errorCode = Integer.parseInt(errorCodeText.getText().toString()); 270 } catch (NumberFormatException e) { 271 Toast.makeText(this, "Couldn't parse reason, defaulting to Unspecified.", 272 Toast.LENGTH_SHORT).show(); 273 } 274 275 int extraCode = ImsReasonInfo.CODE_UNSPECIFIED; 276 try { 277 extraCode = Integer.parseInt(extraCodeText.getText().toString()); 278 } catch (NumberFormatException e) { 279 Toast.makeText(this, "Couldn't parse reason, defaulting to Unspecified.", 280 Toast.LENGTH_SHORT).show(); 281 } 282 283 String message = messageText.getText().toString(); 284 285 ImsReasonInfo result = new ImsReasonInfo(errorCode, extraCode, message); 286 Toast.makeText(this, "getReasonInfo: " + result, Toast.LENGTH_SHORT).show(); 287 return result; 288 } 289 isFrameworkConnected()290 private boolean isFrameworkConnected() { 291 if (TestImsRegistrationImpl.getInstance() == null) { 292 Toast.makeText(this, "Connection to Framework Unavailable!", 293 Toast.LENGTH_LONG).show(); 294 return false; 295 } 296 return true; 297 } 298 } 299