diff options
Diffstat (limited to 'rcs/presencepolling')
7 files changed, 184 insertions, 42 deletions
diff --git a/rcs/presencepolling/Android.bp b/rcs/presencepolling/Android.bp index dfe9f68..ed4a656 100644 --- a/rcs/presencepolling/Android.bp +++ b/rcs/presencepolling/Android.bp @@ -24,12 +24,43 @@ // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. +package { + default_applicable_licenses: ["external_ims_rcs_presencepolling_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "external_ims_rcs_presencepolling_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-BSD", + ], + license_text: [ + "LICENSE", + ], +} + java_defaults { name: "presence_polling_defaults", srcs: ["src/**/*.java"], static_libs: ["com.android.ims.rcsmanager"], - platform_apis: true, certificate: "platform", + system_ext_specific: true, + platform_apis: true, optimize: { proguard_flags_files: ["proguard.flags"], }, diff --git a/rcs/presencepolling/AndroidManifest.xml b/rcs/presencepolling/AndroidManifest.xml index 9ee86ef..2ffcc5c 100644 --- a/rcs/presencepolling/AndroidManifest.xml +++ b/rcs/presencepolling/AndroidManifest.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> +<?xml version="1.0" encoding="utf-8"?> <!-- * Copyright (c) 2015, Motorola Mobility LLC * All rights reserved. @@ -28,20 +28,20 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - package="com.android.service.ims.presence" - android:sharedUserId="android.uid.phone" - coreApp="true"> + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + package="com.android.service.ims.presence" + android:sharedUserId="android.uid.phone" + coreApp="true"> <uses-sdk android:minSdkVersion="19"/> <permission android:name="com.android.rcs.eab.permission.READ_WRITE_EAB" - android:protectionLevel="signatureOrSystem" /> + android:protectionLevel="signatureOrSystem"/> - <protected-broadcast android:name="android.provider.rcs.eab.EAB_NEW_CONTACT_INSERTED" /> - <protected-broadcast android:name="android.provider.rcs.eab.EAB_DATABASE_RESET" /> - <protected-broadcast android:name="com.android.service.ims.presence.capability_polling_retry" /> - <protected-broadcast android:name="com.android.service.ims.presence.periodical_capability_discovery" /> + <protected-broadcast android:name="android.provider.rcs.eab.EAB_NEW_CONTACT_INSERTED"/> + <protected-broadcast android:name="android.provider.rcs.eab.EAB_DATABASE_RESET"/> + <protected-broadcast android:name="com.android.service.ims.presence.capability_polling_retry"/> + <protected-broadcast android:name="com.android.service.ims.presence.periodical_capability_discovery"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.BROADCAST_STICKY"/> @@ -51,64 +51,65 @@ <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> - <uses-permission android:name="android.permission.GET_ACCOUNTS" /> + <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="com.android.rcs.eab.permission.READ_WRITE_EAB"/> <uses-permission android:name="android.permission.READ_PROFILE"/> <uses-permission android:name="com.android.ims.rcs.permission.STATUS_CHANGED"/> <uses-permission android:name="com.android.ims.permission.PRESENCE_ACCESS"/> - <application - android:label="@string/app_label" - android:singleUser="true" - android:process="com.android.ims.rcsservice"> + <application android:label="@string/app_label" + android:singleUser="true" + android:process="com.android.ims.rcsservice"> - <service - android:name=".PollingService" - android:excludeFromRecents="true" - android:singleUser="true" - android:permission="com.android.ims.permission.PRESENCE_ACCESS"> + <service android:name=".PollingService" + android:excludeFromRecents="true" + android:singleUser="true" + android:permission="com.android.ims.permission.PRESENCE_ACCESS"> </service> - <receiver android:name=".DeviceBoot" androidprv:systemUserOnly="true"> + <receiver android:name=".DeviceBoot" + androidprv:systemUserOnly="true" + android:exported="true"> <intent-filter android:priority="103"> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> - <receiver android:name=".DeviceShutdown" androidprv:systemUserOnly="true"> + <receiver android:name=".DeviceShutdown" + androidprv:systemUserOnly="true" + android:exported="true"> <intent-filter> <action android:name="android.intent.action.ACTION_SHUTDOWN"/> </intent-filter> </receiver> <receiver android:name=".AlarmBroadcastReceiver" - androidprv:systemUserOnly="true" - android:permission="com.android.ims.permission.PRESENCE_ACCESS"> + androidprv:systemUserOnly="true" + android:permission="com.android.ims.permission.PRESENCE_ACCESS" + android:exported="true"> <intent-filter> <action android:name="com.android.service.ims.presence.periodical_capability_discovery"/> <action android:name="com.android.service.ims.presence.capability_polling_retry"/> - <action android:name="android.provider.rcs.eab.EAB_NEW_CONTACT_INSERTED" /> + <action android:name="android.provider.rcs.eab.EAB_NEW_CONTACT_INSERTED"/> </intent-filter> </receiver> <service android:name=".PersistService" - android:exported="false" - android:permission="com.android.ims.permission.PRESENCE_ACCESS"> + android:exported="false" + android:permission="com.android.ims.permission.PRESENCE_ACCESS"> <intent-filter> <action android:name="com.android.ims.ACTION_PRESENCE_CHANGED"/> </intent-filter> </service> - <service - android:name="com.android.service.ims.presence.EABService" - android:enabled="true"> + <service android:name="com.android.service.ims.presence.EABService" + android:enabled="true"> </service> - <provider - android:name=".EABProvider" - android:permission="com.android.rcs.eab.permission.READ_WRITE_EAB" - android:exported="true" - android:enabled="true" - android:authorities="com.android.rcs.eab" /> + <provider android:name=".EABProvider" + android:permission="com.android.rcs.eab.permission.READ_WRITE_EAB" + android:exported="true" + android:enabled="true" + android:authorities="com.android.rcs.eab"/> </application> </manifest> diff --git a/rcs/presencepolling/CleanSpec.mk b/rcs/presencepolling/CleanSpec.mk new file mode 100644 index 0000000..f9d044f --- /dev/null +++ b/rcs/presencepolling/CleanSpec.mk @@ -0,0 +1,44 @@ +# Copyright (C) 2021 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. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ***************************************************************** +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER +# ***************************************************************** +# Remove old version of PresencePolling in system, since this moved to system-ext +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/PresencePolling) +# ****************************************************************** +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER +# ****************************************************************** diff --git a/rcs/presencepolling/src/com/android/service/ims/presence/CapabilityPolling.java b/rcs/presencepolling/src/com/android/service/ims/presence/CapabilityPolling.java index d2e2178..5002b60 100644 --- a/rcs/presencepolling/src/com/android/service/ims/presence/CapabilityPolling.java +++ b/rcs/presencepolling/src/com/android/service/ims/presence/CapabilityPolling.java @@ -31,6 +31,7 @@ package com.android.service.ims.presence; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -44,7 +45,9 @@ import android.telephony.PhoneNumberUtils; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.ims.ImsException; +import android.telephony.ims.ImsManager; import android.telephony.ims.ProvisioningManager; +import android.telephony.ims.RcsUceAdapter; import android.text.format.TimeMigrationUtils; import android.text.TextUtils; @@ -62,6 +65,10 @@ public class CapabilityPolling { private Logger logger = Logger.getLogger(this.getClass().getName()); private final Context mContext; + private static final String PERSIST_SERVICE_NAME = + "com.android.service.ims.presence.PersistService"; + private static final String PERSIST_SERVICE_PACKAGE = "com.android.service.ims.presence"; + public static final String ACTION_PERIODICAL_DISCOVERY_ALARM = "com.android.service.ims.presence.periodical_capability_discovery"; private PendingIntent mDiscoveryAlarmIntent = null; @@ -83,6 +90,7 @@ public class CapabilityPolling { private int mPublished = -1; private int mProvisioned = -1; private int mDefaultSubId; + private boolean isInitializing = false; private HandlerThread mDiscoveryThread; private Handler mDiscoveryHandler; @@ -126,6 +134,25 @@ public class CapabilityPolling { } }; + private RcsUceAdapter.OnPublishStateChangedListener mPublishStateCallback = + new RcsUceAdapter.OnPublishStateChangedListener() { + @Override + public void onPublishStateChange(int publishState) { + logger.info("publish state changed: " + publishState); + Intent intent = new Intent(RcsPresence.ACTION_PUBLISH_STATE_CHANGED); + intent.putExtra(RcsPresence.EXTRA_PUBLISH_STATE, publishState); + mContext.sendStickyBroadcast(intent); + launchPersistService(intent); + } + }; + + private void launchPersistService(Intent intent) { + ComponentName component = new ComponentName(PERSIST_SERVICE_PACKAGE, + PERSIST_SERVICE_NAME); + intent.setComponent(component); + mContext.startService(intent); + } + private Runnable mRegisterCallbackRunnable = this::tryProvisioningManagerRegistration; private static CapabilityPolling sInstance = null; @@ -234,6 +261,7 @@ public class CapabilityPolling { cancelDiscoveryAlarm(); clearPollingTasks(); mContext.unregisterReceiver(mReceiver); + unregisterPublishStateChangedCallback(); mDiscoveryThread.quit(); if (SubscriptionManager.isValidSubscriptionId(mDefaultSubId)) { @@ -253,6 +281,29 @@ public class CapabilityPolling { mContext.registerReceiver(mReceiver, intentFilter); } + private void registerPublishStateChangedCallback() { + try { + ImsManager imsManager = + (ImsManager) mContext.getSystemService(Context.TELEPHONY_IMS_SERVICE); + RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(mDefaultSubId).getUceAdapter(); + uceAdapter.addOnPublishStateChangedListener(mContext.getMainExecutor(), + mPublishStateCallback); + } catch (Exception ex) { + logger.warn("register publish state callback failed, exception: " + ex); + } + } + + private void unregisterPublishStateChangedCallback() { + try { + ImsManager imsManager = + (ImsManager) mContext.getSystemService(Context.TELEPHONY_IMS_SERVICE); + RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(mDefaultSubId).getUceAdapter(); + uceAdapter.removeOnPublishStateChangedListener(mPublishStateCallback); + } catch (Exception ex) { + logger.warn("unregister publish state callback failed, exception: " + ex); + } + } + private boolean isPollingReady() { RcsManager rcsManager = RcsManager.getInstance(mContext, 0); if (rcsManager != null) { @@ -423,7 +474,7 @@ public class CapabilityPolling { intent.putExtra("pollingType", type); mDiscoveryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + msec, mDiscoveryAlarmIntent); @@ -755,18 +806,23 @@ public class CapabilityPolling { // Track the default subscription (the closest we can get to MSIM). // call from main thread only. public void handleDefaultSubscriptionChanged(int newDefaultSubId) { - logger.print("registerImsCallbacksAndSetAssociatedSubscription: new default= " + logger.print("handleDefaultSubscriptionChanged: new default= " + newDefaultSubId); + if (!SubscriptionManager.isValidSubscriptionId(newDefaultSubId)) { return; } - if (mDefaultSubId == newDefaultSubId) { + if (isInitializing && (mDefaultSubId == newDefaultSubId)) { return; + } else { + isInitializing = true; } // unregister old default first if (SubscriptionManager.isValidSubscriptionId(mDefaultSubId)) { ProvisioningManager pm = ProvisioningManager.createForSubscriptionId(mDefaultSubId); pm.unregisterProvisioningChangedCallback(mProvisioningManagerCallback); + + unregisterPublishStateChangedCallback(); } // register new default and clear old cached values in EAB only if we are changing the // default sub ID. @@ -783,6 +839,7 @@ public class CapabilityPolling { enqueueSettingsChanged(); // load settings for new default. enqueueProvisionStateChanged(); + registerPublishStateChangedCallback(); } public void tryProvisioningManagerRegistration() { diff --git a/rcs/presencepolling/src/com/android/service/ims/presence/PollingService.java b/rcs/presencepolling/src/com/android/service/ims/presence/PollingService.java index ed511e7..8bfd8d1 100644 --- a/rcs/presencepolling/src/com/android/service/ims/presence/PollingService.java +++ b/rcs/presencepolling/src/com/android/service/ims/presence/PollingService.java @@ -209,6 +209,7 @@ public class PollingService extends Service { logger.info("Starting CapabilityPolling..."); mCapabilityPolling = CapabilityPolling.getInstance(this); mCapabilityPolling.start(); + mCapabilityPolling.handleDefaultSubscriptionChanged(mDefaultSubId); } } diff --git a/rcs/presencepolling/src/com/android/service/ims/presence/PollingTask.java b/rcs/presencepolling/src/com/android/service/ims/presence/PollingTask.java index f3b17dd..b9835bb 100644 --- a/rcs/presencepolling/src/com/android/service/ims/presence/PollingTask.java +++ b/rcs/presencepolling/src/com/android/service/ims/presence/PollingTask.java @@ -201,7 +201,7 @@ public class PollingTask { intent.putExtra("pollingTaskId", mId); mRetryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); @@ -254,4 +254,3 @@ public class PollingTask { return sb.toString(); } } - diff --git a/rcs/presencepolling/tests/Android.bp b/rcs/presencepolling/tests/Android.bp index 3dfc931..9f0bdd1 100644 --- a/rcs/presencepolling/tests/Android.bp +++ b/rcs/presencepolling/tests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "external_ims_rcs_presencepolling_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["external_ims_rcs_presencepolling_license"], +} + android_test { name: "PresencePollingTests", srcs: ["src/**/*.java"], |