cmsdk: Dual SIM support on CM SDK
Signed-off-by: Adnan Begovic <adnan@cyngn.com> Change-Id: I69b349853b0259582956744d9ddd99a187c10fff
This commit is contained in:
parent
7820e6d566
commit
7f50335f2b
|
@ -75,6 +75,19 @@ package cyanogenmod.app {
|
||||||
method public void removeTileAsUser(java.lang.String, int, android.os.UserHandle);
|
method public void removeTileAsUser(java.lang.String, int, android.os.UserHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CMTelephonyManager {
|
||||||
|
method public static cyanogenmod.app.CMTelephonyManager getInstance(android.content.Context);
|
||||||
|
method public java.util.List<android.telephony.SubscriptionInfo> getSubInformation();
|
||||||
|
method public boolean isDataConnectionEnabled();
|
||||||
|
method public boolean isDataConnectionSelectedOnSub(int);
|
||||||
|
method public boolean isSubActive(int);
|
||||||
|
method public void setDataConnectionState(boolean);
|
||||||
|
method public void setDefaultPhoneSub(int);
|
||||||
|
method public void setDefaultSmsSub(int);
|
||||||
|
method public void setSubState(int, boolean);
|
||||||
|
field public static final int ASK_FOR_SUBSCRIPTION_ID = 0; // 0x0
|
||||||
|
}
|
||||||
|
|
||||||
public class CustomTile implements android.os.Parcelable {
|
public class CustomTile implements android.os.Parcelable {
|
||||||
ctor public CustomTile(android.os.Parcel);
|
ctor public CustomTile(android.os.Parcel);
|
||||||
ctor public CustomTile();
|
ctor public CustomTile();
|
||||||
|
@ -364,9 +377,11 @@ package cyanogenmod.platform {
|
||||||
|
|
||||||
public static final class Manifest.permission {
|
public static final class Manifest.permission {
|
||||||
ctor public Manifest.permission();
|
ctor public Manifest.permission();
|
||||||
|
field public static final java.lang.String MODIFY_MSIM_PHONE_STATE = "cyanogenmod.permission.MODIFY_MSIM_PHONE_STATE";
|
||||||
field public static final java.lang.String MODIFY_NETWORK_SETTINGS = "cyanogenmod.permission.MODIFY_NETWORK_SETTINGS";
|
field public static final java.lang.String MODIFY_NETWORK_SETTINGS = "cyanogenmod.permission.MODIFY_NETWORK_SETTINGS";
|
||||||
field public static final java.lang.String MODIFY_SOUND_SETTINGS = "cyanogenmod.permission.MODIFY_SOUND_SETTINGS";
|
field public static final java.lang.String MODIFY_SOUND_SETTINGS = "cyanogenmod.permission.MODIFY_SOUND_SETTINGS";
|
||||||
field public static final java.lang.String PUBLISH_CUSTOM_TILE = "cyanogenmod.permission.PUBLISH_CUSTOM_TILE";
|
field public static final java.lang.String PUBLISH_CUSTOM_TILE = "cyanogenmod.permission.PUBLISH_CUSTOM_TILE";
|
||||||
|
field public static final java.lang.String READ_MSIM_PHONE_STATE = "cyanogenmod.permission.READ_MSIM_PHONE_STATE";
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class R {
|
public final class R {
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015, The CyanogenMod 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 org.cyanogenmod.platform.internal;
|
||||||
|
|
||||||
|
import com.android.server.SystemService;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import cyanogenmod.app.CMContextConstants;
|
||||||
|
import cyanogenmod.app.CMTelephonyManager;
|
||||||
|
import cyanogenmod.app.ICMTelephonyManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal service which manages interactions with the phone and data connection
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class CMTelephonyManagerService extends SystemService {
|
||||||
|
private static final String TAG = "CMTelephonyManagerSrv";
|
||||||
|
private static boolean localLOGD = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
|
private TelephonyManager mTelephonyManager;
|
||||||
|
private final IBinder mService = new ICMTelephonyManager.Stub() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the available SIM subscription information.
|
||||||
|
*
|
||||||
|
* @return The list of SIM subscriptions. The returning list can be null or empty.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<SubscriptionInfo> getSubInformation() {
|
||||||
|
enforceTelephonyReadPermission();
|
||||||
|
return getActiveSubscriptionInfoList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state of the SIM by subscription ID.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid the method will return {@code false}.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to query.
|
||||||
|
* @return {@code true} if the SIM is activated (even without signal or requesting the
|
||||||
|
* PIN/PUK), {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isSubActive(int subId) {
|
||||||
|
enforceTelephonyReadPermission();
|
||||||
|
return CMTelephonyManagerService.this.isSubActive(subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state of one of the SIMs by subscription ID.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid or the SIM already
|
||||||
|
* is in the desired state the method will do nothing.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to set.
|
||||||
|
* @param state {@code true} to activate the SIM, {@code false} to disable.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setSubState(int subId, boolean state) {
|
||||||
|
enforceTelephonyModifyPermission();
|
||||||
|
CMTelephonyManagerService.this.setSubState(subId, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the received subscription received has the data
|
||||||
|
* connection enabled.
|
||||||
|
*
|
||||||
|
* This method will return {@code true} (or {@code false} if inactive on the SIM)
|
||||||
|
* even when an internet connection is active through Wifi/BT.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid the method will return {@code false}.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to query.
|
||||||
|
* @return {@code true} if the data connection is enabled on the SIM, {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isDataConnectionSelectedOnSub(int subId) {
|
||||||
|
enforceTelephonyReadPermission();
|
||||||
|
return CMTelephonyManagerService.this.isDataConnectionSelectedOnSub(subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the network data connection is enabled.
|
||||||
|
*
|
||||||
|
* This method will return {@code true} (or {@code false} if inactive)
|
||||||
|
* even when an internet connection is active through Wifi/BT.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the network data connection is enabled, {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isDataConnectionEnabled() {
|
||||||
|
enforceTelephonyReadPermission();
|
||||||
|
return CMTelephonyManagerService.this.isDataConnectionEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the network data conection active or inactive.
|
||||||
|
*
|
||||||
|
* @param state If {@code true} enables the network data connection, if {@code false} disables it.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setDataConnectionState(boolean state) {
|
||||||
|
enforceTelephonyModifyPermission();
|
||||||
|
CMTelephonyManagerService.this.setDataConnectionState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the data connection state on one of the SIMs by subscription ID.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid or the data connection is already
|
||||||
|
* enabled on the SIM the method will do nothing.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to set the network data connection.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setDataConnectionSelectedOnSub(int subId) {
|
||||||
|
enforceTelephonyModifyPermission();
|
||||||
|
CMTelephonyManagerService.this.setDataConnectionSelectedOnSub(subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default phone used to make phone calls as the one received on subId.
|
||||||
|
*
|
||||||
|
* If 0 is used as a parameter, then the option to choose what SIM to use is
|
||||||
|
* selected.
|
||||||
|
*
|
||||||
|
* @param subId The subscription to set as default for phone calls.
|
||||||
|
* To select SIM when calling use 0.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setDefaultPhoneSub(int subId) {
|
||||||
|
enforceTelephonyModifyPermission();
|
||||||
|
CMTelephonyManagerService.this.setDefaultPhoneSub(subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default phone used to send SMS as the one received on subId.
|
||||||
|
*
|
||||||
|
* If 0 is used as a parameter, then the option to choose what SIM to use is
|
||||||
|
* selected.
|
||||||
|
*
|
||||||
|
* @param subId The subscription to set as default for sending SMS.
|
||||||
|
* To select SIM when sending SMS use 0.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setDefaultSmsSub(int subId) {
|
||||||
|
enforceTelephonyModifyPermission();
|
||||||
|
CMTelephonyManagerService.this.setDefaultSmsSub(subId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public CMTelephonyManagerService(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "CM telephony manager service start: " + this);
|
||||||
|
}
|
||||||
|
publishBinderService(CMContextConstants.CM_TELEPHONY_MANAGER_SERVICE, mService);
|
||||||
|
|
||||||
|
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
|
||||||
|
SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
|
||||||
|
List<SubscriptionInfo> subInfoList = subscriptionManager.getActiveSubscriptionInfoList();
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "The active subscriptions where obtained from the subscription manager.");
|
||||||
|
}
|
||||||
|
return subInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSubActive(int subId) {
|
||||||
|
boolean validSubscriptionId = SubscriptionManager.isValidSubscriptionId(subId);
|
||||||
|
|
||||||
|
if (validSubscriptionId) {
|
||||||
|
int simState = SubscriptionManager.getSimStateForSubscriber(subId);
|
||||||
|
switch (simState) {
|
||||||
|
case TelephonyManager.SIM_STATE_ABSENT:
|
||||||
|
case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
|
||||||
|
case TelephonyManager.SIM_STATE_PERM_DISABLED:
|
||||||
|
case TelephonyManager.SIM_STATE_NOT_READY:
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "The subscription " + subId + " is NOT active: " + simState);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "The subscription " + subId + " is active: " + simState);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Invalid subscription identifier: " + subId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSubState(int subId, boolean state) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Setting the subscription " + subId + " to inactive (false) or active (true): " + state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
SubscriptionManager.activateSubId(subId);
|
||||||
|
} else {
|
||||||
|
SubscriptionManager.deactivateSubId(subId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDataConnectionSelectedOnSub(int subId) {
|
||||||
|
boolean validSubscriptionId = SubscriptionManager.isValidSubscriptionId(subId);
|
||||||
|
|
||||||
|
if (validSubscriptionId) {
|
||||||
|
if (subId == SubscriptionManager.getDefaultDataSubId()) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Data connection selected for subscription " + subId);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Data connection not selected for subscription " + subId);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Invalid subscription identifier: " + subId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDataConnectionEnabled() {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Checking if the network data connection is active");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean dataEnabled = mTelephonyManager.getDataEnabled();
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Data network connection is inactive (false) or active (true): " + dataEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataConnectionState(boolean state) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Setting the network data connection inactive (false) or active (true): " + state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
mTelephonyManager.enableDataConnectivity();
|
||||||
|
} else {
|
||||||
|
mTelephonyManager.disableDataConnectivity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataConnectionSelectedOnSub(int subId) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Setting the network data connection for subscription " + subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
|
||||||
|
subscriptionManager.setDefaultDataSubId(subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDefaultPhoneSub(int subId) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Setting the SIM for phone calls on subscription " + subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
|
||||||
|
if (subId == CMTelephonyManager.ASK_FOR_SUBSCRIPTION_ID) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Activates the prompt for phone calls");
|
||||||
|
}
|
||||||
|
SubscriptionManager.setVoicePromptEnabled(true);
|
||||||
|
} else {
|
||||||
|
SubscriptionManager.setVoicePromptEnabled(false);
|
||||||
|
subscriptionManager.setDefaultVoiceSubId(subId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDefaultSmsSub(int subId) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Setting the SIM for phone calls on subscription " + subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
|
||||||
|
if (subId == CMTelephonyManager.ASK_FOR_SUBSCRIPTION_ID) {
|
||||||
|
if (localLOGD) {
|
||||||
|
Log.d(TAG, "Activates the prompt for SMS");
|
||||||
|
}
|
||||||
|
SubscriptionManager.setSMSPromptEnabled(true);
|
||||||
|
} else {
|
||||||
|
SubscriptionManager.setSMSPromptEnabled(false);
|
||||||
|
subscriptionManager.setDefaultSmsSubId(subId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enforceTelephonyReadPermission() {
|
||||||
|
mContext.enforceCallingOrSelfPermission(
|
||||||
|
cyanogenmod.platform.Manifest.permission.READ_MSIM_PHONE_STATE,
|
||||||
|
"CMTelephonyManagerService");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enforceTelephonyModifyPermission() {
|
||||||
|
mContext.enforceCallingOrSelfPermission(
|
||||||
|
cyanogenmod.platform.Manifest.permission.MODIFY_MSIM_PHONE_STATE,
|
||||||
|
"CMTelephonyManagerService");
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,20 @@
|
||||||
android:icon="@drawable/ic_launcher_cyanogenmod"
|
android:icon="@drawable/ic_launcher_cyanogenmod"
|
||||||
android:protectionLevel="normal" />
|
android:protectionLevel="normal" />
|
||||||
|
|
||||||
|
<!-- Allows a 3rd party to view the phone SIM states and data connection -->
|
||||||
|
<permission android:name="cyanogenmod.permission.READ_MSIM_PHONE_STATE"
|
||||||
|
android:label="@string/permlab_readMSPhoneState"
|
||||||
|
android:description="@string/permdesc_readMSPhoneState"
|
||||||
|
android:icon="@drawable/ic_launcher_cyanogenmod"
|
||||||
|
android:protectionLevel="normal" />
|
||||||
|
|
||||||
|
<!-- Allows a 3rd party to modify the phone SIM states and data connection -->
|
||||||
|
<permission android:name="cyanogenmod.permission.MODIFY_MSIM_PHONE_STATE"
|
||||||
|
android:label="@string/permlab_modifyMSPhoneState"
|
||||||
|
android:description="@string/permdesc_modifyMSPhoneState"
|
||||||
|
android:icon="@drawable/ic_launcher_cyanogenmod"
|
||||||
|
android:protectionLevel="normal" />
|
||||||
|
|
||||||
<application android:process="system"
|
<application android:process="system"
|
||||||
android:persistent="true"
|
android:persistent="true"
|
||||||
android:hasCode="false"
|
android:hasCode="false"
|
||||||
|
|
|
@ -30,6 +30,14 @@
|
||||||
<string name="permlab_bindCustomTileListenerService">bind to a custom tile listener service</string>
|
<string name="permlab_bindCustomTileListenerService">bind to a custom tile listener service</string>
|
||||||
<string name="permdesc_bindCustomTileListenerService">Allows the app to bind to the top-level interface of a custom tile listener service.</string>
|
<string name="permdesc_bindCustomTileListenerService">Allows the app to bind to the top-level interface of a custom tile listener service.</string>
|
||||||
|
|
||||||
|
<!-- Labels for the READ_MSIM_PHONE_STATE permission. -->
|
||||||
|
<string name="permlab_readMSPhoneState">view the phone state and data connection with support to multiple SIMs</string>
|
||||||
|
<string name="permdesc_readMSPhoneState">Allows an app to view the phone state and data connection with support to multiple SIMs.</string>
|
||||||
|
|
||||||
|
<!-- Labels for the MODIFY_MSIM_PHONE_STATE permission. -->
|
||||||
|
<string name="permlab_modifyMSPhoneState">modify the phone state and data connection with support to multiple SIMs</string>
|
||||||
|
<string name="permdesc_modifyMSPhoneState">Allows an app to modify the phone state and data connection with support to multiple SIMs.</string>
|
||||||
|
|
||||||
<!-- Label to show for a service that is running because it is observing the user's custom tiles. -->
|
<!-- Label to show for a service that is running because it is observing the user's custom tiles. -->
|
||||||
<string name="custom_tile_listener_binding_label">Custom tile listener</string>
|
<string name="custom_tile_listener_binding_label">Custom tile listener</string>
|
||||||
|
|
||||||
|
|
|
@ -61,4 +61,16 @@ public final class CMContextConstants {
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final String CM_SETTINGS_SERVICE = "cmsettings";
|
public static final String CM_SETTINGS_SERVICE = "cmsettings";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use with {@link android.content.Context#getSystemService} to retrieve a
|
||||||
|
* {@link cyanogenmod.app.CMTelephonyManager} to manage the phone and
|
||||||
|
* data connection.
|
||||||
|
*
|
||||||
|
* @see android.content.Context#getSystemService
|
||||||
|
* @see cyanogenmod.app.CMTelephonyManager
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String CM_TELEPHONY_MANAGER_SERVICE = "cmtelephonymanager";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,349 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015, The CyanogenMod 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 cyanogenmod.app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CMTelephonyManager allows you to view and manage the phone state and
|
||||||
|
* the data connection, with multiple SIMs support.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* To get the instance of this class, utilize CMTelephonyManager#getInstance(Context context)
|
||||||
|
*/
|
||||||
|
public class CMTelephonyManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription ID used to set the default Phone and SMS to "ask every time".
|
||||||
|
*/
|
||||||
|
public static final int ASK_FOR_SUBSCRIPTION_ID = 0;
|
||||||
|
|
||||||
|
private static final String TAG = "CMTelephonyManager";
|
||||||
|
private static boolean localLOGD = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
|
private static ICMTelephonyManager sService;
|
||||||
|
private static CMTelephonyManager sCMTelephonyManagerInstance;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
private CMTelephonyManager(Context context) {
|
||||||
|
Context appContext = context.getApplicationContext();
|
||||||
|
if (appContext != null) {
|
||||||
|
mContext = appContext;
|
||||||
|
} else {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
sService = getService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or create an instance of the {@link cyanogenmod.app.CMTelephonyManager}
|
||||||
|
*
|
||||||
|
* @return {@link cyanogenmod.app.CMTelephonyManager}
|
||||||
|
*/
|
||||||
|
public static CMTelephonyManager getInstance(Context context) {
|
||||||
|
if (sCMTelephonyManagerInstance == null) {
|
||||||
|
sCMTelephonyManagerInstance = new CMTelephonyManager(context);
|
||||||
|
}
|
||||||
|
return sCMTelephonyManagerInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public ICMTelephonyManager getService() {
|
||||||
|
if (sService != null) {
|
||||||
|
return sService;
|
||||||
|
}
|
||||||
|
IBinder b = ServiceManager.getService(CMContextConstants.CM_TELEPHONY_MANAGER_SERVICE);
|
||||||
|
if (b != null) {
|
||||||
|
sService = ICMTelephonyManager.Stub.asInterface(b);
|
||||||
|
return sService;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of {@link SubscriptionInfo} that are registered on the
|
||||||
|
* phone.
|
||||||
|
*
|
||||||
|
* @return The list of SIM subscriptions. The returning list can be null or empty.
|
||||||
|
* @see SubscriptionInfo
|
||||||
|
*/
|
||||||
|
public List<SubscriptionInfo> getSubInformation() {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting the SIMs information");
|
||||||
|
}
|
||||||
|
List<SubscriptionInfo> subInfoList = null;
|
||||||
|
try {
|
||||||
|
subInfoList = sService.getSubInformation();
|
||||||
|
if (subInfoList == null) {
|
||||||
|
Log.w(TAG, "no subscription list was returned from the service");
|
||||||
|
} else if (subInfoList.isEmpty()) {
|
||||||
|
Log.w(TAG, "the subscription list is empty");
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
|
||||||
|
return subInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state of the SIM by subscription ID.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid the method will return {@code false}.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to query.
|
||||||
|
* @return {@code true} if the SIM is activated (even without signal or requesting the
|
||||||
|
* PIN/PUK), {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isSubActive(int subId) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting the state of the SIM with subscription: " + subId);
|
||||||
|
}
|
||||||
|
boolean simActive = false;
|
||||||
|
try {
|
||||||
|
simActive = sService.isSubActive(subId);
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting the SIM state with subscription " + subId + " as active: " + simActive);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
|
||||||
|
return simActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state of one of the SIMs by subscription ID.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid or the SIM already
|
||||||
|
* is in the desired state the method will do nothing.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to change the state.
|
||||||
|
* @param state {@code true} to activate the SIM, {@code false} to disable.
|
||||||
|
*/
|
||||||
|
public void setSubState(int subId, boolean state) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " setting the state of the SIM with subscription " + subId + " as active: " + state);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sService.setSubState(subId, state);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the received subscription received has the data
|
||||||
|
* connection enabled.
|
||||||
|
*
|
||||||
|
* This method will return {@code true} (or {@code false} if inactive on the SIM)
|
||||||
|
* even when an internet connection is active through Wifi/BT.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid the method will return false.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to query.
|
||||||
|
* @return {@code true} if the data connection is enabled on the SIM, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isDataConnectionSelectedOnSub(int subId) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting if the data connection is enabled for SIM for subscription: " + subId);
|
||||||
|
}
|
||||||
|
boolean dataConnectionActiveOnSim = false;
|
||||||
|
try {
|
||||||
|
dataConnectionActiveOnSim = sService.isDataConnectionSelectedOnSub(subId);
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting if the data connection is enabled for SIM with subscription " +
|
||||||
|
subId + " as active: " + dataConnectionActiveOnSim);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataConnectionActiveOnSim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the network data connection is enabled.
|
||||||
|
*
|
||||||
|
* This method will return {@code true} (or {@code false} if inactive)
|
||||||
|
* even when an internet connection is active through Wifi/BT.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the network data connection is enabled, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isDataConnectionEnabled() {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting if the network data connection is enabled");
|
||||||
|
}
|
||||||
|
boolean dataConnectionEnabled = false;
|
||||||
|
try {
|
||||||
|
dataConnectionEnabled = sService.isDataConnectionEnabled();
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " getting if the network data connection is enabled: " + dataConnectionEnabled);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataConnectionEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the network data conection active or inactive.
|
||||||
|
*
|
||||||
|
* @param state If {@code true} enables the network data connection, if {@code false} disables it.
|
||||||
|
*/
|
||||||
|
public void setDataConnectionState(boolean state) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " setting the network data connection enabled: " + state);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sService.setDataConnectionState(state);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the data connection state on one of the SIMs by subscription ID.
|
||||||
|
*
|
||||||
|
* If the subscription ID is not valid or the data connection is already
|
||||||
|
* enabled on the SIM the method will do nothing.
|
||||||
|
*
|
||||||
|
* @param subId The subscription ID to set the network data connection.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setDataConnectionSelectedOnSub(int subId) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " setting the network data connection for SIM with subscription: " + subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sService.setDataConnectionSelectedOnSub(subId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default phone used to make phone calls as the one received on subId.
|
||||||
|
*
|
||||||
|
* If ASK_FOR_SUBSCRIPTION_ID is used as a parameter, then the option to choose
|
||||||
|
* what SIM to use is selected.
|
||||||
|
*
|
||||||
|
* @param subId The subscription to set as default for phone calls.
|
||||||
|
* To select SIM when calling use ASK_FOR_SUBSCRIPTION_ID.
|
||||||
|
*/
|
||||||
|
public void setDefaultPhoneSub(int subId) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " setting the subscription used for phone calls as: " + subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sService.setDefaultPhoneSub(subId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default phone used to send SMS as the one received on subId.
|
||||||
|
*
|
||||||
|
* If ASK_FOR_SUBSCRIPTION_ID is used as a parameter, then the option to choose
|
||||||
|
* what SIM to use is selected.
|
||||||
|
*
|
||||||
|
* @param subId The subscription to set as default for sending SMS.
|
||||||
|
* To select SIM when sending SMS use ASK_FOR_SUBSCRIPTION_ID.
|
||||||
|
*/
|
||||||
|
public void setDefaultSmsSub(int subId) {
|
||||||
|
if (sService == null) {
|
||||||
|
Log.w(TAG, "not connected to CMTelephonyManager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localLOGD) {
|
||||||
|
String pkg = mContext.getPackageName();
|
||||||
|
Log.v(TAG, pkg + " setting the subscription used for SMS as: " + subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sService.setDefaultSmsSub(subId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "warning: no cm telephony manager service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015, The CyanogenMod 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 cyanogenmod.app;
|
||||||
|
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
interface ICMTelephonyManager {
|
||||||
|
// --- Methods below are for use by 3rd party applications to manage phone and data connection
|
||||||
|
// You need the READ_MSIM_PHONE_STATE permission
|
||||||
|
List<SubscriptionInfo> getSubInformation();
|
||||||
|
boolean isSubActive(int subId);
|
||||||
|
boolean isDataConnectionSelectedOnSub(int subId);
|
||||||
|
boolean isDataConnectionEnabled();
|
||||||
|
|
||||||
|
// You need the MODIFY_MSIM_PHONE_STATE permission
|
||||||
|
void setSubState(int subId, boolean state);
|
||||||
|
void setDataConnectionSelectedOnSub(int subId);
|
||||||
|
void setDataConnectionState(boolean state);
|
||||||
|
void setDefaultPhoneSub(int subId);
|
||||||
|
void setDefaultSmsSub(int subId);
|
||||||
|
}
|
|
@ -75,6 +75,19 @@ package cyanogenmod.app {
|
||||||
method public void removeTileAsUser(java.lang.String, int, android.os.UserHandle);
|
method public void removeTileAsUser(java.lang.String, int, android.os.UserHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CMTelephonyManager {
|
||||||
|
method public static cyanogenmod.app.CMTelephonyManager getInstance(android.content.Context);
|
||||||
|
method public java.util.List<android.telephony.SubscriptionInfo> getSubInformation();
|
||||||
|
method public boolean isDataConnectionEnabled();
|
||||||
|
method public boolean isDataConnectionSelectedOnSub(int);
|
||||||
|
method public boolean isSubActive(int);
|
||||||
|
method public void setDataConnectionState(boolean);
|
||||||
|
method public void setDefaultPhoneSub(int);
|
||||||
|
method public void setDefaultSmsSub(int);
|
||||||
|
method public void setSubState(int, boolean);
|
||||||
|
field public static final int ASK_FOR_SUBSCRIPTION_ID = 0; // 0x0
|
||||||
|
}
|
||||||
|
|
||||||
public class CustomTile implements android.os.Parcelable {
|
public class CustomTile implements android.os.Parcelable {
|
||||||
ctor public CustomTile(android.os.Parcel);
|
ctor public CustomTile(android.os.Parcel);
|
||||||
ctor public CustomTile();
|
ctor public CustomTile();
|
||||||
|
@ -364,9 +377,11 @@ package cyanogenmod.platform {
|
||||||
|
|
||||||
public static final class Manifest.permission {
|
public static final class Manifest.permission {
|
||||||
ctor public Manifest.permission();
|
ctor public Manifest.permission();
|
||||||
|
field public static final java.lang.String MODIFY_MSIM_PHONE_STATE = "cyanogenmod.permission.MODIFY_MSIM_PHONE_STATE";
|
||||||
field public static final java.lang.String MODIFY_NETWORK_SETTINGS = "cyanogenmod.permission.MODIFY_NETWORK_SETTINGS";
|
field public static final java.lang.String MODIFY_NETWORK_SETTINGS = "cyanogenmod.permission.MODIFY_NETWORK_SETTINGS";
|
||||||
field public static final java.lang.String MODIFY_SOUND_SETTINGS = "cyanogenmod.permission.MODIFY_SOUND_SETTINGS";
|
field public static final java.lang.String MODIFY_SOUND_SETTINGS = "cyanogenmod.permission.MODIFY_SOUND_SETTINGS";
|
||||||
field public static final java.lang.String PUBLISH_CUSTOM_TILE = "cyanogenmod.permission.PUBLISH_CUSTOM_TILE";
|
field public static final java.lang.String PUBLISH_CUSTOM_TILE = "cyanogenmod.permission.PUBLISH_CUSTOM_TILE";
|
||||||
|
field public static final java.lang.String READ_MSIM_PHONE_STATE = "cyanogenmod.permission.READ_MSIM_PHONE_STATE";
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class R {
|
public final class R {
|
||||||
|
|
Loading…
Reference in New Issue