diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 0c0c338..13cec1d 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -3,7 +3,20 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a7ceea1..97a641b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,6 +13,7 @@
+
-
+
diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/CallReceiver.java b/app/src/main/java/com/app/simplitend/patient_dashboard/CallReceiver.java
index 8c569f8..25b43b6 100644
--- a/app/src/main/java/com/app/simplitend/patient_dashboard/CallReceiver.java
+++ b/app/src/main/java/com/app/simplitend/patient_dashboard/CallReceiver.java
@@ -1,18 +1,197 @@
package com.app.simplitend.patient_dashboard;
+import static com.app.simplitend.callwhitelisting.CallUnBlockingWorker.CALL_BLOCKING_WORk;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.telecom.TelecomManager;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkManager;
+import androidx.work.WorkRequest;
+
+import com.app.simplitend.apputils.AppUtil;
+import com.app.simplitend.callwhitelisting.CallUnBlockingWorker;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
public class CallReceiver extends BroadcastReceiver {
private static final String TAG = "CallReceiver";
+ private static int lastState = TelephonyManager.CALL_STATE_IDLE;
+ private static Date callStartTime;
+ private static boolean isIncoming;
+ private static String savedNumber; //because the passed incoming is only valid in ringing
+
@Override
public void onReceive(Context context, Intent intent) {
- TelecomManager telecomManager = (TelecomManager) context.getApplicationContext().getSystemService(TelecomManager.class);
+ if (intent.getExtras() == null) {
+ Log.d(TAG, "onReceive: EXTRAS ARE NULL");
+ return;
+ }
+
+// logBundle(intent.getExtras());
+
+ String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
+ String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
+
+ int state = 0;
+ if (TelephonyManager.EXTRA_STATE_IDLE.equals(stateStr)) {
+ state = TelephonyManager.CALL_STATE_IDLE;
+ } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(stateStr)) {
+ state = TelephonyManager.CALL_STATE_OFFHOOK;
+ } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(stateStr)) {
+ state = TelephonyManager.CALL_STATE_RINGING;
+ }
+
+ onCallStateChanged(context, state, number);
}
-}
+ protected void logBundle(Bundle bundle) {
+ if (bundle != null) {
+ for (String key : bundle.keySet()) {
+ Log.e(TAG, key + " : " + (bundle.get(key) != null ? bundle.get(key) : "NULL"));
+ }
+ }
+ }
+
+ //Derived classes should override these to respond to specific events of interest
+ protected void onIncomingCallStarted(Context ctx, String number, Date start) {
+ Log.d(TAG, "onIncomingCallStarted: " + number);
+ if (!AppUtil.isCallBlockingEnabled(ctx)) {
+ // senior has deactivated the call blocking feature
+ Log.d(TAG, "onIncomingCallStarted: CALL BLOCKING IS DEACTIVATED");
+ return;
+ }
+
+ try {
+ Phonenumber.PhoneNumber parsed_phone = PhoneNumberUtil.getInstance().parse(number, "US");
+ number = "+" + parsed_phone.getCountryCode() + parsed_phone.getNationalNumber();
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ Log.d(TAG, "AFTER FORMATTING PHONE NUMBER -> " + number);
+
+ Set white_contacts = AppUtil.getWhiteListedContacts(ctx);
+ Log.d(TAG, "WHITE LISTED CONTACTS -> " + white_contacts);
+
+ if (AppUtil.isUserSubscribed(ctx) && white_contacts != null && !white_contacts.contains(number)) {
+ disconnectCall();
+ Log.d(TAG, "CALL ENDED");
+ }
+
+ }
+
+ public void disconnectCall(){
+ try {
+ String serviceManagerName = "android.os.ServiceManager";
+ String serviceManagerNativeName = "android.os.ServiceManagerNative";
+ String telephonyName = "com.android.internal.telephony.ITelephony";
+ Class> telephonyClass;
+ Class> telephonyStubClass;
+ Class> serviceManagerClass;
+ Class> serviceManagerNativeClass;
+ Method telephonyEndCall;
+ Object telephonyObject;
+ Object serviceManagerObject;
+ telephonyClass = Class.forName(telephonyName);
+ telephonyStubClass = telephonyClass.getClasses()[0];
+ serviceManagerClass = Class.forName(serviceManagerName);
+ serviceManagerNativeClass = Class.forName(serviceManagerNativeName);
+ Method getService = // getDefaults[29];
+ serviceManagerClass.getMethod("getService", String.class);
+ Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class);
+ Binder tmpBinder = new Binder();
+ tmpBinder.attachInterface(null, "fake");
+ serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
+ IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
+ Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);
+ telephonyObject = serviceMethod.invoke(null, retbinder);
+ telephonyEndCall = telephonyClass.getMethod("endCall");
+ telephonyEndCall.invoke(telephonyObject);
+
+ } catch (Exception e) {
+ Log.e(TAG,
+ "FATAL ERROR: could not connect to telephony subsystem");
+ Log.e(TAG, "Exception object: " + e);
+ }
+ }
+
+ protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
+ Log.d(TAG, "onOutgoingCallStarted: " + number);
+ if ("911".equals(number)){
+ Log.d(TAG, "CALLED 911");
+ WorkManager.getInstance(ctx).cancelAllWorkByTag(TAG);
+ WorkRequest workRequest = new OneTimeWorkRequest.Builder(CallUnBlockingWorker.class)
+ .setInitialDelay(30, TimeUnit.MINUTES)
+ .addTag(CALL_BLOCKING_WORk)
+ .build();
+
+ WorkManager.getInstance(ctx).enqueue(workRequest);
+
+ AppUtil.setIsCallBlockingEnabled(ctx, false);
+ Log.d(TAG, "CALL BLOCKING DISABLED");
+ }
+ }
+
+ protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
+ }
+
+ protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
+ }
+
+ protected void onMissedCall(Context ctx, String number, Date start) {
+ }
+
+ //Deals with actual events
+
+ //Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
+ //Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
+ public void onCallStateChanged(Context context, int state, String number) {
+ if (lastState == state) {
+ //No change, debounce extras
+ return;
+ }
+ switch (state) {
+ case TelephonyManager.CALL_STATE_RINGING:
+ isIncoming = true;
+ callStartTime = new Date();
+ savedNumber = number;
+ onIncomingCallStarted(context, number, callStartTime);
+ break;
+ case TelephonyManager.CALL_STATE_OFFHOOK:
+ //Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
+ if (lastState != TelephonyManager.CALL_STATE_RINGING) {
+ isIncoming = false;
+ callStartTime = new Date();
+ onOutgoingCallStarted(context, number, callStartTime);
+ }
+ break;
+ case TelephonyManager.CALL_STATE_IDLE:
+ //Went to idle- this is the end of a call. What type depends on previous state(s)
+ if (lastState == TelephonyManager.CALL_STATE_RINGING) {
+ //Ring but no pickup- a miss
+ onMissedCall(context, savedNumber, callStartTime);
+ } else if (isIncoming) {
+ onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
+ } else {
+ onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
+ }
+ break;
+ }
+ lastState = state;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java b/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java
index 9a935c9..a31400f 100644
--- a/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java
+++ b/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java
@@ -78,7 +78,6 @@ public class DashBoardActivity extends AppCompatActivity implements CgHomeContra
}), null, null);
}
- requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 1212);
});
registerForActivityResult(new ActivityResultContracts.RequestPermission(),
@@ -94,6 +93,8 @@ public class DashBoardActivity extends AppCompatActivity implements CgHomeContra
RoleManager roleManager = getSystemService(RoleManager.class);
Intent i = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
startActivityForResult(i, 1214, null);
+ }else{
+ requestPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.READ_PHONE_STATE, Manifest.permission.ANSWER_PHONE_CALLS}, 1212);
}
}
}).launch(Manifest.permission.READ_CONTACTS);
diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/PatSettingsActivity.java b/app/src/main/java/com/app/simplitend/patient_dashboard/PatSettingsActivity.java
index 252fdad..1f4b865 100644
--- a/app/src/main/java/com/app/simplitend/patient_dashboard/PatSettingsActivity.java
+++ b/app/src/main/java/com/app/simplitend/patient_dashboard/PatSettingsActivity.java
@@ -1,8 +1,10 @@
package com.app.simplitend.patient_dashboard;
+import static com.app.simplitend.callwhitelisting.CallUnBlockingWorker.CALL_BLOCKING_WORk;
import static com.app.simplitend.caregiverdashboard.activities.deactivateacc.DeActivateAccountActivity.IS_PATIENT_KEY;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.work.WorkManager;
import android.app.ProgressDialog;
import android.content.Context;
@@ -74,6 +76,9 @@ public class PatSettingsActivity extends AppCompatActivity implements CgHomeCont
binding.callBlockCheck.setOnCheckedChangeListener(null);
binding.callBlockCheck.setChecked(true);
binding.callBlockCheck.setOnCheckedChangeListener(this);
+
+ WorkManager.getInstance(PatSettingsActivity.this)
+ .cancelAllWorkByTag(CALL_BLOCKING_WORk);
}),
"Turn off", ((dialogInterface, i) -> {
AppUtil.setIsCallBlockingEnabled(PatSettingsActivity.this, false);