Merge the android-9.0.0_r60 release tag
Android 9.0.0 release 60
* tag 'android-9.0.0_r60':
Restrict access to the resolution PendingIntent created by EuiccController to EuiccResolutionUiDispatcherActivity
Specify the component for the ACTION_SHOW_ECM_EXIT_DIALOG Intent
Change-Id: Ibfd83b9773426d5a388b75323abea8c9ebcce544
diff --git a/Android.mk b/Android.mk
index e30a4fc..1070732 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,7 +19,8 @@
android-support-v7-appcompat \
android-support-v7-preference \
android-support-v7-recyclerview \
- android-support-v14-preference
+ android-support-v14-preference \
+ android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES := \
guava \
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 13fd30a..33cd319 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -607,5 +607,6 @@
<action android:name="android.telephony.data.DataService" />
</intent-filter>
</service>
+ <service android:name=".SpecialCarrierAppIntentService" />
</application>
</manifest>
diff --git a/res/drawable/ic_special_carrier_app_disable.xml b/res/drawable/ic_special_carrier_app_disable.xml
new file mode 100644
index 0000000..480c19a
--- /dev/null
+++ b/res/drawable/ic_special_carrier_app_disable.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
+</vector>
diff --git a/res/drawable/ic_special_carrier_app_enable.xml b/res/drawable/ic_special_carrier_app_enable.xml
new file mode 100644
index 0000000..edaf734
--- /dev/null
+++ b/res/drawable/ic_special_carrier_app_enable.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
+</vector>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 20a5cbb..201e7be 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -747,4 +747,10 @@
<string name="supp_service_forwarded_call" msgid="4509980341645679803">"Appel transféré."</string>
<string name="supp_service_conference_call" msgid="4448616364004466832">"Connexion en cours à la conférence téléphonique."</string>
<string name="supp_service_held_call_released" msgid="2030677825038709779">"L\'appel en attente a été interrompu."</string>
+ <string name="special_carrier_app_disable">"Désactiver"</string>
+ <string name="special_carrier_app_enable">"Activer"</string>
+ <string name="special_carrier_app_generic_carrier_name">"Votre opérateur"</string>
+ <string name="special_carrier_app_for_uicc">"Application opérateur"</string>
+ <string name="special_carrier_app_summary">"%1$s vous propose une application."</string>
+ <string name="special_carrier_app_summary_extended">"%1$s vous propose une application. Voulez-vous l'activer ?"</string>
</resources>
diff --git a/res/values-mcc208-mnc01-fr/strings.xml b/res/values-mcc208-mnc01-fr/strings.xml
new file mode 100644
index 0000000..f016d42
--- /dev/null
+++ b/res/values-mcc208-mnc01-fr/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="special_carrier_app_summary">"Orange vous propose l’application Apps Orange."</string>
+ <string name="special_carrier_app_summary_extended">"Orange vous propose l’application Apps Orange. Apps Orange offre un accès rapide à un catalogue d’applications Orange et partenaires. Voulez-vous l’activer ?"</string>
+</resources>
diff --git a/res/values-mcc208-mnc02-fr b/res/values-mcc208-mnc02-fr
new file mode 120000
index 0000000..45a205d
--- /dev/null
+++ b/res/values-mcc208-mnc02-fr
@@ -0,0 +1 @@
+values-mcc208-mnc01-fr
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f728109..ae269ec 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1748,4 +1748,23 @@
<!-- Message displayed to the user to indicate that a held call has been released /
disconnected. -->
<string name="supp_service_held_call_released">Held call has been released.</string>
+
+ <!-- Special Carrier App notification -->
+ <!-- [CHAR LIMIT=25] Button to disable a special carrier app. -->
+ <string name="special_carrier_app_disable">Disable</string>
+ <!-- [CHAR LIMIT=25] Button to enable special carrier app. -->
+ <string name="special_carrier_app_enable">Enable</string>
+ <!-- Generic carrier name in case the carrier name is not available. -->
+ <string name="special_carrier_app_generic_carrier_name">Your operator</string>
+ <!-- [CHAR_LIMIT=24] -->
+ <string name="special_carrier_app_for_uicc">Special operator app</string>
+ <!-- [CHAR_LIMIT=40] Arguments: <Operator name> -->
+ <string name="special_carrier_app_summary"><xliff:g id="operator" example="Your operator">%1$s</xliff:g> offers a special app.</string>
+ <!-- Arguments: <Operator name> -->
+ <string name="special_carrier_app_summary_extended"><xliff:g id="operator" example="Your operator">%1$s</xliff:g> offers a special app. Do you want to enable it?</string>
+
+ <!-- Notification channel configuration -->
+ <string name="notification_channel_id">notification_channel_01</string>
+ <string name="notification_channel_name">Notifications</string>
+ <string name="notification_channel_description">Notifications</string>
</resources>
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 691d9ff..0f9ec9e 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -318,6 +318,7 @@
private MyHandler mHandler;
private boolean mOkClicked;
private boolean mExpandAdvancedFields;
+ private boolean canPreferenceChange;
// We assume the the value returned by mTabHost.getCurrentTab() == slotId
private TabHost mTabHost;
@@ -933,6 +934,11 @@
final PreferenceScreen prefSet = getPreferenceScreen();
final int phoneSubId = mPhone.getSubId();
final boolean hasActiveSubscriptions = hasActiveSubscriptions();
+ Context context = activity.getApplicationContext();
+ int network_mode = android.provider.Settings.Global.getInt(
+ context.getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ preferredNetworkMode);
if (activity == null || activity.isDestroyed()) {
Log.e(LOG_TAG, "updateBody with no valid activity.");
@@ -946,6 +952,23 @@
prefSet.removeAll();
+ if(phoneSubId != SubscriptionManager.getDefaultDataSubscriptionId()) {
+ if(network_mode == Phone.NT_MODE_LTE_GSM_WCDMA) {
+ android.provider.Settings.Global.putInt(
+ context.getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ Phone.NT_MODE_GSM_ONLY);
+ }
+ }
+ else if(phoneSubId == SubscriptionManager.getDefaultDataSubscriptionId() && !canPreferenceChange){
+ if(network_mode == Phone.NT_MODE_GSM_ONLY) {
+ android.provider.Settings.Global.putInt(
+ context.getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
+ Phone.NT_MODE_LTE_GSM_WCDMA);
+ }
+ canPreferenceChange = false;
+ }
updateBodyBasicFields(activity, prefSet, phoneSubId, hasActiveSubscriptions);
if (mExpandAdvancedFields) {
@@ -1152,6 +1175,11 @@
.setOnPreferenceChangeListener(this);
}
+ boolean canChangeNetworkMode = true;
+ if ((settingsNetworkMode == Phone.NT_MODE_GSM_ONLY) && (phoneSubId != SubscriptionManager.getDefaultDataSubscriptionId())) {
+ canChangeNetworkMode = false;
+ }
+
// Get the networkMode from Settings.System and displays it
mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
@@ -1177,7 +1205,7 @@
R.string.enhanced_4g_lte_mode_title;
mButtonPreferredNetworkMode.setEnabled(hasActiveSubscriptions);
- mButtonEnabledNetworks.setEnabled(hasActiveSubscriptions);
+ mButtonEnabledNetworks.setEnabled(hasActiveSubscriptions && canChangeNetworkMode);
mButton4glte.setTitle(enhanced4glteModeTitleId);
mLteDataServicePref.setEnabled(hasActiveSubscriptions);
Preference ps;
@@ -1289,6 +1317,7 @@
.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE));
}
} else if (preference == mButtonEnabledNetworks) {
+ canPreferenceChange = true;
mButtonEnabledNetworks.setValue((String) objValue);
int buttonNetworkMode;
buttonNetworkMode = Integer.parseInt((String) objValue);
diff --git a/src/com/android/phone/SpecialCarrierAppIntentService.java b/src/com/android/phone/SpecialCarrierAppIntentService.java
new file mode 100644
index 0000000..440a3ad
--- /dev/null
+++ b/src/com/android/phone/SpecialCarrierAppIntentService.java
@@ -0,0 +1,211 @@
+package com.android.phone;
+
+import android.app.IntentService;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.support.v4.app.NotificationCompat;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.telephony.SpecialCarrierAppInfo;
+
+public class SpecialCarrierAppIntentService extends IntentService {
+
+ private static final String TAG = "SpecialCarrierApp";
+
+ private static final boolean DEBUG = false; // STOPSHIP if true
+
+ /**
+ * Action to handle a match.
+ * The app will be enabled if it matched while the device was not provisioned, otherwise
+ * a notification will be displayed to let the user enable the app (or not).
+ */
+ public static final String ACTION_HANDLE_MATCH = "com.android.phone.SpecialCarrierApp.handle_match";
+ /**
+ * Action to dismiss the offer to enable/disable the carrier app (will be offered again).
+ */
+ public static final String ACTION_DISMISS_OFFER = "com.android.phone.SpecialCarrierApp.dismiss_notification";
+ /**
+ * Action to enable the app.
+ */
+ public static final String ACTION_ENABLE_APP = "com.android.phone.SpecialCarrierApp.enable_app";
+ /**
+ * Action to disable the app.
+ */
+ public static final String ACTION_DISABLE_APP = "com.android.phone.SpecialCarrierApp.disable_app";
+
+ public static final String EXTRA_APP_INFO = "com.android.phone.SpecialCarrierApp.app_info";
+ public static final String EXTRA_DEVICE_PROVISIONED = "com.android.phone.SpecialCarrierApp.device_provisioned";
+
+ private IPackageManager mPackageManager;
+
+ public SpecialCarrierAppIntentService() {
+ super("SpecialCarrierAppIntentService");
+
+ mPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ }
+
+ public static PendingIntent getPendingDismissIntent(Context context, SpecialCarrierAppInfo appInfo) {
+ final Intent intent = new Intent(context, SpecialCarrierAppIntentService.class)
+ .setAction(ACTION_DISMISS_OFFER)
+ .putExtra(EXTRA_APP_INFO, appInfo);
+ return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ }
+
+ public static PendingIntent getPendingEnableIntent(Context context, SpecialCarrierAppInfo appInfo) {
+ final Intent intent = new Intent(context, SpecialCarrierAppIntentService.class)
+ .setAction(ACTION_ENABLE_APP)
+ .putExtra(EXTRA_APP_INFO, appInfo);
+ return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ }
+
+ public static PendingIntent getPendingDisableIntent(Context context, SpecialCarrierAppInfo appInfo) {
+ final Intent intent = new Intent(context, SpecialCarrierAppIntentService.class)
+ .setAction(ACTION_DISABLE_APP)
+ .putExtra(EXTRA_APP_INFO, appInfo);
+ return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ if (intent != null) {
+ final String action = intent.getAction();
+ if (DEBUG) Slog.d(TAG, "Received intent with action: " + action);
+
+ final Object appInfoObject = intent.getSerializableExtra(EXTRA_APP_INFO);
+ if (appInfoObject == null || !(appInfoObject instanceof SpecialCarrierAppInfo)) {
+ Slog.wtf(TAG, "EXTRA_APP_INFO is mandatory");
+ return;
+ }
+ final SpecialCarrierAppInfo appInfo = (SpecialCarrierAppInfo) appInfoObject;
+
+ if (ACTION_DISMISS_OFFER.equals(action)) {
+ handleActionDismissOffer(appInfo);
+ } else if (ACTION_ENABLE_APP.equals(action)) {
+ handleActionEnableApp(appInfo);
+ } else if (ACTION_DISABLE_APP.equals(action)) {
+ handleActionDisableApp(appInfo);
+ } else if (ACTION_HANDLE_MATCH.equals(action)) {
+ handleActionHandleMatch(appInfo,
+ intent.getBooleanExtra(EXTRA_DEVICE_PROVISIONED, true));
+ } else {
+ Slog.w(TAG, "Unknown action: " + action);
+ }
+ }
+ }
+
+ private void handleActionDismissOffer(SpecialCarrierAppInfo appInfo) {
+ Slog.d(TAG, "Dismissed, the special carrier app " + appInfo.mPackageName + " will be offered again.");
+ }
+
+ private void handleActionHandleMatch(SpecialCarrierAppInfo appInfo, boolean wasDeviceProvisioned) {
+ if (!wasDeviceProvisioned) {
+ if (DEBUG) Slog.d(TAG, "The device was not yet provisioned when the special carrier app matched.");
+
+ enableSpecialCarrierApp(appInfo);
+ } else {
+ if (DEBUG) Slog.d(TAG, "The device was already provisioned when the special carrier app matched.");
+
+ showNotification(appInfo);
+ }
+ }
+
+ private void handleActionEnableApp(SpecialCarrierAppInfo appInfo) {
+ enableSpecialCarrierApp(appInfo);
+ cancelNotification(appInfo);
+ }
+
+ private void handleActionDisableApp(SpecialCarrierAppInfo appInfo) {
+ disableSpecialCarrierApp(appInfo);
+ cancelNotification(appInfo);
+ }
+
+ private void showNotification(SpecialCarrierAppInfo appInfo) {
+ createNotificationChannel(getApplicationContext());
+ final int slotNumberToDisplay = appInfo.mUiccSlotId + 1;
+
+ if (TextUtils.isEmpty(appInfo.mCarrierName)) {
+ appInfo.mCarrierName = getString(R.string.special_carrier_app_generic_carrier_name);
+ }
+
+ final String channelId = getString(R.string.notification_channel_id);
+ final Notification notification =
+ new NotificationCompat.Builder(getApplicationContext(), channelId)
+ .setDeleteIntent(getPendingDismissIntent(getApplicationContext(), appInfo))
+ .setContentTitle(getString(R.string.special_carrier_app_for_uicc))
+ .setContentText(getString(R.string.special_carrier_app_summary, appInfo.mCarrierName))
+ .setSmallIcon(com.android.internal.R.drawable.ic_sim_card_multi_48px_clr)
+ .setStyle(new NotificationCompat.BigTextStyle().bigText(
+ getString(R.string.special_carrier_app_summary_extended, appInfo.mCarrierName, slotNumberToDisplay)))
+ .addAction(
+ new NotificationCompat.Action.Builder(
+ R.drawable.ic_special_carrier_app_disable,
+ getString(R.string.special_carrier_app_disable),
+ getPendingDisableIntent(getApplicationContext(), appInfo)).build())
+ .addAction(
+ new NotificationCompat.Action.Builder(
+ R.drawable.ic_special_carrier_app_enable,
+ getString(R.string.special_carrier_app_enable),
+ getPendingEnableIntent(getApplicationContext(), appInfo)).build())
+ .build();
+
+ ((NotificationManager) getApplicationContext()
+ .getSystemService(Context.NOTIFICATION_SERVICE)
+ ).notify(appInfo.mUiccSlotId, notification);
+ }
+
+ private void createNotificationChannel(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ String channelId = context.getString(R.string.notification_channel_id);
+ CharSequence name = context.getString(R.string.notification_channel_name);
+ String description = context.getString(R.string.notification_channel_description);
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+
+ NotificationChannel channel = new NotificationChannel(channelId, name, importance);
+ channel.setDescription(description);
+ ((NotificationManager) getApplicationContext()
+ .getSystemService(Context.NOTIFICATION_SERVICE)
+ ).createNotificationChannel(channel);
+ }
+ }
+
+ private void cancelNotification(SpecialCarrierAppInfo appInfo) {
+ ((NotificationManager) getApplicationContext()
+ .getSystemService(Context.NOTIFICATION_SERVICE)
+ ).cancel(appInfo.mUiccSlotId);
+ }
+
+ private void enableSpecialCarrierApp(SpecialCarrierAppInfo appInfo) {
+ updateCarrierAppState(appInfo, true);
+ if (appInfo.mActionIntentToBroadcast != null) {
+ getApplicationContext().sendBroadcast(new Intent(appInfo.mActionIntentToBroadcast));
+ }
+ }
+
+ private void disableSpecialCarrierApp(SpecialCarrierAppInfo appInfo) {
+ updateCarrierAppState(appInfo, false);
+ }
+
+ private void updateCarrierAppState(SpecialCarrierAppInfo appInfo, boolean enable) {
+ Slog.i(TAG, "Update state(" + appInfo.mPackageName + "): " + (enable ? "ENABLED" : "DISABLED")
+ + " for user " + getApplicationContext().getUserId());
+ try {
+ mPackageManager.setApplicationEnabledSetting(appInfo.mPackageName,
+ enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
+ enable ? PackageManager.DONT_KILL_APP : 0, getApplicationContext().getUserId(),
+ getApplicationContext().getOpPackageName());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not reach PackageManager", e);
+ }
+ }
+}