那些年,我在VVM中趟過的坑

最近,客戶提出一個需求,要加設備中加入VVM相關。

VVM簡介

VVM配置:

客戶提供了一個VVM配置信息,如下:.

Orange France (208/01)

Type : vvm_type_omtp
Dest Number : 21101
Dest port : 20481
vvm package : com.orange.vvm
prefetch : true
cellular data : true
ssl port : 0
legacy mode : false
disabled capabilities : STARTTLS
client prefix: //VVM

配置的信息,主要包含於Package/apps/CarrierConfig中,具體配置爲:

packages/apps/CarrierConfig/assets/carrier_config_20801.xml

<!--Visual voicemail config-->
<!--VVM Type-->
<string name="vvm_type_string">vvm_type_omtp</string>
<!--VVM Dest Number-->
<string name="vvm_destination_number_string">21101</string>
<!--VVM Dest port-->
<int name="vvm_port_number_int" value="20481"/>
<!--VVM package-->
<string-array name="carrier_vvm_package_name_string_array" num="1">
    <item value="com.orange.vvm"/>
</string-array>
<!--VVM prefetch-->
<boolean name="vvm_prefetch_bool" value="true"/>
<!--VVM cellular data-->
<boolean name="vvm_cellular_data_required_bool" value="true"/>
<!--VVM ssl port-->
<int name="vvm_ssl_port_number_int" value="0"/>
<!--VVM legacy mode-->
<boolean name="vvm_legacy_mode_enabled_bool" value="false"/>
<!--VVM disabled capabilities-->
<string-array name="vvm_disabled_capabilities_string_array" num="1">
    <item value="STARTTLS"/>
</string-array>
<!--VVM client prefix-->
<string name="vvm_client_prefix_string">//VVM</string>

配置完成後,插入對應Orange SIM卡後,運行正常。

 

經由客戶測試後,反饋一個bug,安裝運營商的VVM應用後,原生VVM自動禁用,但是卸載VVM後,原生代碼沒有自動開啓。

查看對應的代碼,發現目前只對應用的安裝進行了監聽,並未對應用卸載進行監聽,具體如下:

packages/services/Telephony/src/com/android/phone/vvm/CarrierVvmPackageInstalledReceiver.java

public void register(Context context) {
    IntentFilter intentFilter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
    intentFilter.addDataScheme("package");
    context.registerReceiver(this, intentFilter);
}

對應的處理類中,也只對安裝進行了處理,具體如下:

packages/apps/Dialer/java/com/android/voicemail/impl/VvmPackageInstallHandler.java

public static void handlePackageInstalled(Context context, String packageName) {...}

因此我們只需加入對應的處理即可,修改代碼如下:

packages/services/Telephony/src/com/android/phone/vvm/CarrierVvmPackageInstalledReceiver.java

+    private static final String ACTION_CARRIER_VVM_PACKAGE_UNINSTALLED =
+            "com.android.internal.telephony.CARRIER_VVM_PACKAGE_UNINSTALLED";
+
     public void register(Context context) {
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
         intentFilter.addDataScheme("package");
         context.registerReceiver(this, intentFilter);
+        IntentFilter uninstallFilter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+        uninstallFilter.addDataScheme("package");
+        context.registerReceiver(this, uninstallFilter);
     }

     @Override
     public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+            if (intent.getData() == null) {
+                return;
             }

+            String packageName = intent.getData().getSchemeSpecificPart();
+            if (packageName == null) {
+                return;
             }
+            TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+            String systemDialer = telecomManager.getSystemDialerPackage();
+            TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+            for (PhoneAccountHandle phoneAccountHandle : telecomManager.getCallCapablePhoneAccounts()) {
+                TelephonyManager pinnedTelephonyManager = telephonyManager
+                        .createForPhoneAccountHandle(phoneAccountHandle);
+
+                if (pinnedTelephonyManager == null) {
+                    VvmLog.e(TAG, "cannot create TelephonyManager from " + phoneAccountHandle);
+                    continue;
+                }
+
+                if (!getCarrierVvmPackages(telephonyManager).contains(packageName)) {
+                    continue;
+                }
+
+                VvmLog.i(TAG, "Carrier VVM app " + packageName + " installed");
+
+                String vvmPackage = pinnedTelephonyManager.getVisualVoicemailPackageName();
+                if (!TextUtils.equals(vvmPackage, systemDialer)) {
+                    // Non system dialer do not need to prioritize carrier vvm app.
+                    VvmLog.i(TAG, "non system dialer " + vvmPackage + " ignored");
+                    continue;
+                }
+
+                VvmLog.i(TAG, "sending broadcast to " + vvmPackage);
+                Intent broadcast = new Intent(ACTION_CARRIER_VVM_PACKAGE_INSTALLED);
+                broadcast.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+                broadcast.setPackage(vvmPackage);
+                context.sendBroadcast(broadcast);
+            }
+        } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+            if (intent.getData() == null) {
+                return;
+            }
+            String packageName = intent.getData().getSchemeSpecificPart();
+            if (packageName == null) {
+                return;
             }
+            TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+            String systemDialer = telecomManager.getSystemDialerPackage();
+            TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+            for (PhoneAccountHandle phoneAccountHandle : telecomManager.getCallCapablePhoneAccounts()) {
+                TelephonyManager pinnedTelephonyManager = telephonyManager
+                        .createForPhoneAccountHandle(phoneAccountHandle);
+
+                if (pinnedTelephonyManager == null) {
+                    VvmLog.e(TAG, "cannot create TelephonyManager from " + phoneAccountHandle);
+                    continue;
+                }
+
+                if (!getCarrierVvmPackages(telephonyManager).contains(packageName)) {
+                    continue;
+                }
+
+                VvmLog.i(TAG, "Carrier VVM app " + packageName + " uninstalled");
+
+                String vvmPackage = pinnedTelephonyManager.getVisualVoicemailPackageName();
+                if (!TextUtils.equals(vvmPackage, systemDialer)) {
+                    // Non system dialer do not need to prioritize carrier vvm app.
+                    VvmLog.i(TAG, "non system dialer " + vvmPackage + " ignored");
+                    continue;
+                }
+
+                VvmLog.i(TAG, "sending broadcast to " + vvmPackage);
+                Intent broadcast = new Intent(ACTION_CARRIER_VVM_PACKAGE_UNINSTALLED);
+                broadcast.putExtra("carrier_vvm_uninstall", packageName);
+                broadcast.setPackage(vvmPackage);
+                context.sendBroadcast(broadcast);
+            }
+        }

packages/apps/Dialer/java/com/android/voicemail/impl/AndroidManifest.xml

<!-- system dialer only broadcast -->
         <action
             android:name="com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED" />
+        <action
+            android:name="com.android.internal.telephony.CARRIER_VVM_PACKAGE_UNINSTALLED" />

packages/apps/Dialer/java/com/android/voicemail/impl/CarrierVvmPackageInstalledReceiver.java

+  private static final String ACTION_CARRIER_VVM_PACKAGE_INSTALLED =
+            "com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED";
+
+  private static final String ACTION_CARRIER_VVM_PACKAGE_UNINSTALLED =
+            "com.android.internal.telephony.CARRIER_VVM_PACKAGE_UNINSTALLED";
+
   @Override
   public void onReceive(Context context, Intent intent) {
-    String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
-    VvmLog.i("CarrierVvmPackageInstalledReceiver.onReceive", "package installed: " + packageName);
-    VvmPackageInstallHandler.handlePackageInstalled(context, packageName);
+       String action = intent.getAction();
+       if (ACTION_CARRIER_VVM_PACKAGE_INSTALLED.equals(action)) {
+               String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+           VvmLog.i("CarrierVvmPackageInstalledReceiver.onReceive", "package installed: " + packageName);
+           VvmPackageInstallHandler.handlePackageInstalled(context, packageName);
+       } else if (ACTION_CARRIER_VVM_PACKAGE_UNINSTALLED.equals(action)) {
+               String uninstall = intent.getStringExtra("carrier_vvm_uninstall");
+        VvmLog.i("CarrierVvmPackageInstalledReceiver.onReceive", "package uninstalled: " + uninstall);
+        VvmPackageInstallHandler.handlePackageUninstalled(context, uninstall);
+       }
   }

packages/apps/Dialer/java/com/android/voicemail/impl/VvmPackageInstallHandler.java

if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) {

+      /*if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) {
         // Skip the check if this voicemail source's setting is overridden by the user.
         VvmLog.i(
             "VvmPackageInstallHandler.handlePackageInstalled",
             "VVM enabled by user, not disabling");
         continue;
-      }
+      }*/

       // Force deactivate the client. The user can re-enable it in the settings.
       // There is no need to update the settings for deactivation. At this point, if the
@@ -77,4 +79,30 @@ public final class VvmPackageInstallHandler {
       VisualVoicemailSettingsUtil.setEnabled(context, phoneAccount, false);
     }
   }
+

+  public static void handlePackageUninstalled(Context context, String packageName) {
+    // This get called every time an app is installed and will be noisy. Don't log until the app
+    // is identified as a carrier VVM app.
+    for (PhoneAccountHandle phoneAccount :
+        context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) {
+      OmtpVvmCarrierConfigHelper carrierConfigHelper =
+          new OmtpVvmCarrierConfigHelper(context, phoneAccount);
+      if (!carrierConfigHelper.isValid()) {
+        continue;
+      }
+      if (carrierConfigHelper.getCarrierVvmPackageNames() == null) {
+        continue;
+      }
+      if (!carrierConfigHelper.getCarrierVvmPackageNames().contains(packageName)) {
+        continue;
+      }
+
+      VvmLog.i("VvmPackageInstallHandler.handlePackageUninstalled", "Carrier app uninstalled");
+
+      // Force activate the client. The user can disable it in the settings.
+      VisualVoicemailSettingsUtil.setEnabled(context, phoneAccount, true);
+    }
+  }

修改後,自測通過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章