414 lines
15 KiB
Java
414 lines
15 KiB
Java
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.deviceinfo;
|
|
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.res.Resources;
|
|
import android.os.Bundle;
|
|
import android.os.SystemProperties;
|
|
import android.os.UserHandle;
|
|
import android.preference.Preference;
|
|
import android.preference.PreferenceActivity;
|
|
import android.telephony.CellBroadcastMessage;
|
|
import android.telephony.PhoneNumberUtils;
|
|
import android.telephony.PhoneStateListener;
|
|
import android.telephony.ServiceState;
|
|
import android.telephony.SignalStrength;
|
|
import android.telephony.SubscriptionInfo;
|
|
import android.telephony.SubscriptionManager;
|
|
import android.telephony.TelephonyManager;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import com.android.internal.telephony.DefaultPhoneNotifier;
|
|
import com.android.internal.telephony.Phone;
|
|
import com.android.internal.telephony.PhoneFactory;
|
|
import com.android.settings.R;
|
|
import com.android.settings.Utils;
|
|
|
|
import android.view.View;
|
|
import android.widget.ListView;
|
|
import android.widget.TabHost;
|
|
import android.widget.TabHost.OnTabChangeListener;
|
|
import android.widget.TabHost.TabContentFactory;
|
|
import android.widget.TabHost.TabSpec;
|
|
import android.widget.TabWidget;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
|
|
/**
|
|
* Display the following information
|
|
* # Phone Number
|
|
* # Network
|
|
* # Roaming
|
|
* # Device Id (IMEI in GSM and MEID in CDMA)
|
|
* # Network type
|
|
* # Operator info (area info cell broadcast for Brazil)
|
|
* # Signal Strength
|
|
*
|
|
*/
|
|
public class SimStatus extends PreferenceActivity {
|
|
private static final String TAG = "SimStatus";
|
|
|
|
private static final String KEY_DATA_STATE = "data_state";
|
|
private static final String KEY_SERVICE_STATE = "service_state";
|
|
private static final String KEY_OPERATOR_NAME = "operator_name";
|
|
private static final String KEY_ROAMING_STATE = "roaming_state";
|
|
private static final String KEY_NETWORK_TYPE = "network_type";
|
|
private static final String KEY_LATEST_AREA_INFO = "latest_area_info";
|
|
private static final String KEY_PHONE_NUMBER = "number";
|
|
private static final String KEY_SIGNAL_STRENGTH = "signal_strength";
|
|
private static final String KEY_IMEI = "imei";
|
|
private static final String KEY_IMEI_SV = "imei_sv";
|
|
private static final String COUNTRY_ABBREVIATION_BRAZIL = "br";
|
|
|
|
static final String CB_AREA_INFO_RECEIVED_ACTION =
|
|
"android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
|
|
|
|
static final String GET_LATEST_CB_AREA_INFO_ACTION =
|
|
"android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
|
|
|
|
// Require the sender to have this permission to prevent third-party spoofing.
|
|
static final String CB_AREA_INFO_SENDER_PERMISSION =
|
|
"android.permission.RECEIVE_EMERGENCY_BROADCAST";
|
|
|
|
|
|
private TelephonyManager mTelephonyManager;
|
|
private Phone mPhone = null;
|
|
private Resources mRes;
|
|
private Preference mSignalStrength;
|
|
private SubscriptionInfo mSir;
|
|
private boolean mShowLatestAreaInfo;
|
|
|
|
// Default summary for items
|
|
private String mDefaultText;
|
|
|
|
private TabHost mTabHost;
|
|
private TabWidget mTabWidget;
|
|
private ListView mListView;
|
|
private List<SubscriptionInfo> mSelectableSubInfos;
|
|
|
|
private PhoneStateListener mPhoneStateListener;
|
|
private BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
String action = intent.getAction();
|
|
if (CB_AREA_INFO_RECEIVED_ACTION.equals(action)) {
|
|
Bundle extras = intent.getExtras();
|
|
if (extras == null) {
|
|
return;
|
|
}
|
|
CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
|
|
if (cbMessage != null
|
|
&& cbMessage.getServiceCategory() == 50
|
|
&& mSir.getSubscriptionId() == cbMessage.getSubId()) {
|
|
String latestAreaInfo = cbMessage.getMessageBody();
|
|
updateAreaInfo(latestAreaInfo);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
@Override
|
|
protected void onCreate(Bundle icicle) {
|
|
super.onCreate(icicle);
|
|
|
|
mSelectableSubInfos = new ArrayList<SubscriptionInfo>();
|
|
mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
|
|
|
addPreferencesFromResource(R.xml.device_info_sim_status);
|
|
|
|
mRes = getResources();
|
|
mDefaultText = mRes.getString(R.string.device_info_default);
|
|
// Note - missing in zaku build, be careful later...
|
|
mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH);
|
|
|
|
for (int i = 0; i < mTelephonyManager.getSimCount(); i++) {
|
|
final SubscriptionInfo sir = Utils.findRecordBySlotId(this, i);
|
|
if (sir != null) {
|
|
mSelectableSubInfos.add(sir);
|
|
}
|
|
}
|
|
|
|
mSir = mSelectableSubInfos.get(0);
|
|
if (mSelectableSubInfos.size() > 1) {
|
|
setContentView(R.layout.sim_information);
|
|
|
|
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
|
|
mTabWidget = (TabWidget) findViewById(android.R.id.tabs);
|
|
mListView = (ListView) findViewById(android.R.id.list);
|
|
|
|
mTabHost.setup();
|
|
mTabHost.setOnTabChangedListener(mTabListener);
|
|
mTabHost.clearAllTabs();
|
|
|
|
for (int i = 0; i < mSelectableSubInfos.size(); i++) {
|
|
mTabHost.addTab(buildTabSpec(String.valueOf(i),
|
|
String.valueOf(mSelectableSubInfos.get(i).getDisplayName())));
|
|
}
|
|
}
|
|
|
|
updatePhoneInfos();
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
if (mPhone != null) {
|
|
updatePreference();
|
|
|
|
updateSignalStrength(mPhone.getSignalStrength());
|
|
updateServiceState(mPhone.getServiceState());
|
|
updateDataState();
|
|
mTelephonyManager.listen(mPhoneStateListener,
|
|
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
|
|
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
|
|
| PhoneStateListener.LISTEN_SERVICE_STATE);
|
|
if (mShowLatestAreaInfo) {
|
|
registerReceiver(mAreaInfoReceiver, new IntentFilter(CB_AREA_INFO_RECEIVED_ACTION),
|
|
CB_AREA_INFO_SENDER_PERMISSION, null);
|
|
// Ask CellBroadcastReceiver to broadcast the latest area info received
|
|
Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
|
|
sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
|
|
CB_AREA_INFO_SENDER_PERMISSION);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onPause() {
|
|
super.onPause();
|
|
|
|
if (mPhone != null) {
|
|
mTelephonyManager.listen(mPhoneStateListener,
|
|
PhoneStateListener.LISTEN_NONE);
|
|
}
|
|
if (mShowLatestAreaInfo) {
|
|
unregisterReceiver(mAreaInfoReceiver);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes the specified preference, if it exists.
|
|
* @param key the key for the Preference item
|
|
*/
|
|
private void removePreferenceFromScreen(String key) {
|
|
Preference pref = findPreference(key);
|
|
if (pref != null) {
|
|
getPreferenceScreen().removePreference(pref);
|
|
}
|
|
}
|
|
|
|
private void setSummaryText(String key, String text) {
|
|
if (TextUtils.isEmpty(text)) {
|
|
text = mDefaultText;
|
|
}
|
|
// some preferences may be missing
|
|
final Preference preference = findPreference(key);
|
|
if (preference != null) {
|
|
preference.setSummary(text);
|
|
}
|
|
}
|
|
|
|
private void updateNetworkType() {
|
|
// Whether EDGE, UMTS, etc...
|
|
String networktype = null;
|
|
if (TelephonyManager.NETWORK_TYPE_UNKNOWN
|
|
!= mTelephonyManager.getNetworkType(mSir.getSubscriptionId())) {
|
|
networktype = mTelephonyManager.getNetworkTypeName(
|
|
mTelephonyManager.getNetworkType(mSir.getSubscriptionId()));
|
|
}
|
|
setSummaryText(KEY_NETWORK_TYPE, networktype);
|
|
}
|
|
|
|
private void updateDataState() {
|
|
final int state =
|
|
DefaultPhoneNotifier.convertDataState(mPhone.getDataConnectionState());
|
|
|
|
String display = mRes.getString(R.string.radioInfo_unknown);
|
|
|
|
switch (state) {
|
|
case TelephonyManager.DATA_CONNECTED:
|
|
display = mRes.getString(R.string.radioInfo_data_connected);
|
|
break;
|
|
case TelephonyManager.DATA_SUSPENDED:
|
|
display = mRes.getString(R.string.radioInfo_data_suspended);
|
|
break;
|
|
case TelephonyManager.DATA_CONNECTING:
|
|
display = mRes.getString(R.string.radioInfo_data_connecting);
|
|
break;
|
|
case TelephonyManager.DATA_DISCONNECTED:
|
|
display = mRes.getString(R.string.radioInfo_data_disconnected);
|
|
break;
|
|
}
|
|
|
|
setSummaryText(KEY_DATA_STATE, display);
|
|
}
|
|
|
|
private void updateServiceState(ServiceState serviceState) {
|
|
final int state = serviceState.getState();
|
|
String display = mRes.getString(R.string.radioInfo_unknown);
|
|
|
|
switch (state) {
|
|
case ServiceState.STATE_IN_SERVICE:
|
|
display = mRes.getString(R.string.radioInfo_service_in);
|
|
break;
|
|
case ServiceState.STATE_OUT_OF_SERVICE:
|
|
case ServiceState.STATE_EMERGENCY_ONLY:
|
|
display = mRes.getString(R.string.radioInfo_service_out);
|
|
break;
|
|
case ServiceState.STATE_POWER_OFF:
|
|
display = mRes.getString(R.string.radioInfo_service_off);
|
|
break;
|
|
}
|
|
|
|
setSummaryText(KEY_SERVICE_STATE, display);
|
|
|
|
if (serviceState.getRoaming()) {
|
|
setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in));
|
|
} else {
|
|
setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_not));
|
|
}
|
|
setSummaryText(KEY_OPERATOR_NAME, serviceState.getOperatorAlphaLong());
|
|
}
|
|
|
|
private void updateAreaInfo(String areaInfo) {
|
|
if (areaInfo != null) {
|
|
setSummaryText(KEY_LATEST_AREA_INFO, areaInfo);
|
|
}
|
|
}
|
|
|
|
void updateSignalStrength(SignalStrength signalStrength) {
|
|
if (mSignalStrength != null) {
|
|
final int state = mPhone.getServiceState().getState();
|
|
Resources r = getResources();
|
|
|
|
if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
|
|
(ServiceState.STATE_POWER_OFF == state)) {
|
|
mSignalStrength.setSummary("0");
|
|
}
|
|
|
|
int signalDbm = signalStrength.getDbm();
|
|
int signalAsu = signalStrength.getAsuLevel();
|
|
|
|
if (-1 == signalDbm) {
|
|
signalDbm = 0;
|
|
}
|
|
|
|
if (-1 == signalAsu) {
|
|
signalAsu = 0;
|
|
}
|
|
|
|
mSignalStrength.setSummary(r.getString(R.string.sim_signal_strength,
|
|
signalDbm, signalAsu));
|
|
}
|
|
}
|
|
|
|
private void updatePreference() {
|
|
if (mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) {
|
|
// only show area info when SIM country is Brazil
|
|
if (COUNTRY_ABBREVIATION_BRAZIL.equals(mTelephonyManager.getSimCountryIso(
|
|
mSir.getSubscriptionId()))) {
|
|
mShowLatestAreaInfo = true;
|
|
}
|
|
}
|
|
|
|
String rawNumber = mPhone.getLine1Number(); // may be null or empty
|
|
String formattedNumber = null;
|
|
if (!TextUtils.isEmpty(rawNumber)) {
|
|
formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
|
|
}
|
|
// If formattedNumber is null or empty, it'll display as "Unknown".
|
|
setSummaryText(KEY_PHONE_NUMBER, formattedNumber);
|
|
final String imei = mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA
|
|
? mPhone.getImei() : mPhone.getDeviceId();
|
|
setSummaryText(KEY_IMEI, imei);
|
|
setSummaryText(KEY_IMEI_SV,
|
|
((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
|
|
.getDeviceSoftwareVersion(/*slotId*/));
|
|
|
|
if (!mShowLatestAreaInfo) {
|
|
removePreferenceFromScreen(KEY_LATEST_AREA_INFO);
|
|
}
|
|
}
|
|
|
|
private void updatePhoneInfos() {
|
|
final Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(
|
|
mSir.getSubscriptionId()));
|
|
if (UserHandle.myUserId() == UserHandle.USER_OWNER
|
|
&& mSir.getSubscriptionId() != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
|
if (phone == null) {
|
|
Log.e(TAG, "Unable to locate a phone object for the given Subscription ID.");
|
|
return;
|
|
}
|
|
|
|
mPhone = phone;
|
|
mPhoneStateListener = new PhoneStateListener(mSir.getSubscriptionId()) {
|
|
@Override
|
|
public void onDataConnectionStateChanged(int state) {
|
|
updateDataState();
|
|
updateNetworkType();
|
|
}
|
|
|
|
@Override
|
|
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
|
|
updateSignalStrength(signalStrength);
|
|
}
|
|
|
|
@Override
|
|
public void onServiceStateChanged(ServiceState serviceState) {
|
|
updateServiceState(serviceState);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
private OnTabChangeListener mTabListener = new OnTabChangeListener() {
|
|
@Override
|
|
public void onTabChanged(String tabId) {
|
|
final int slotId = Integer.parseInt(tabId);
|
|
mSir = mSelectableSubInfos.get(slotId);
|
|
|
|
// The User has changed tab; update the SIM information.
|
|
updatePhoneInfos();
|
|
mTelephonyManager.listen(mPhoneStateListener,
|
|
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
|
|
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
|
|
| PhoneStateListener.LISTEN_SERVICE_STATE);
|
|
updateDataState();
|
|
updateNetworkType();
|
|
updatePreference();
|
|
}
|
|
};
|
|
|
|
private TabContentFactory mEmptyTabContent = new TabContentFactory() {
|
|
@Override
|
|
public View createTabContent(String tag) {
|
|
return new View(mTabHost.getContext());
|
|
}
|
|
};
|
|
|
|
private TabSpec buildTabSpec(String tag, String title) {
|
|
return mTabHost.newTabSpec(tag).setIndicator(title).setContent(
|
|
mEmptyTabContent);
|
|
}
|
|
}
|