* Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *  CSipSimple is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *  CSipSimple is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  GNU General Public License for more details.
 *  You should have received a copy of the GNU General Public License
 *  along with CSipSimple.  If not, see <http://www.gnu.org/licenses/>.

package com.csipsimple.utils;

import android.Manifest.permission;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;

import com.csipsimple.api.SipManager;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class RewriterPlugin {

    private static final String THIS_FILE = "RewriterPlugin";
    public static final String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";

    private static Map<String, String> AVAILABLE_REWRITERS = null;

     * Rewrite a number using a given plugin.
     * Warning this should never be done on main thread otherwise will always fail due to thread issues.
     * @param context The application context to use to talk to plugin
     * @param componentName The fully qualified component name of the plugin
     * @param number The number to rewrite
    public static String rewriteNumber(Context context, final String componentName, String number) {
        ComponentName cn = ComponentName.unflattenFromString(componentName);

        Intent it = new Intent(SipManager.ACTION_REWRITE_NUMBER);
        it.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
        OnRewriteReceiver resultTreater = new OnRewriteReceiver(number);
        context.sendOrderedBroadcast(it, permission.PROCESS_OUTGOING_CALLS, resultTreater, null,
                Activity.RESULT_OK, null, null);
        return resultTreater.getResult();

     * Retrieve rewriter available as plugin for csipsimple.
     * @param ctxt context of application
     * @return A map of package name => Fancy name of rewriter
    public static Map<String, String> getAvailableRewriters(Context ctxt) {

        if (AVAILABLE_REWRITERS == null) {
            AVAILABLE_REWRITERS = new HashMap<String, String>();

            PackageManager packageManager = ctxt.getPackageManager();
            Intent it = new Intent(SipManager.ACTION_REWRITE_NUMBER);

            List<ResolveInfo> availables = packageManager.queryBroadcastReceivers(it, 0);
            for (ResolveInfo resInfo : availables) {
                ActivityInfo actInfos = resInfo.activityInfo;
                Log.d(THIS_FILE, "Found rewriter " + actInfos.packageName + " " + actInfos.name);
                if (packageManager.checkPermission(permission.PROCESS_OUTGOING_CALLS,
                        actInfos.packageName) == PackageManager.PERMISSION_GRANTED) {
                    String packagedActivityName = (new ComponentName(actInfos.packageName,
                            (String) resInfo.loadLabel(packageManager));


     * Reset cache of outgoing call handlers
    public static void clearAvailableRewriters() {

     * Interface for listener about load state of remote call handler plugin
    public static class OnRewriteReceiver extends BroadcastReceiver {
        String result;
        private Semaphore runSemaphore;

        public OnRewriteReceiver(String defaultResult) {
            result = defaultResult;
            runSemaphore = new Semaphore(0);
        public void onReceive(Context context, Intent intent) {
            Log.d(THIS_FILE, "Rewriter receive");
            Bundle resolvedInfos = getResultExtras(true);
            result = resolvedInfos.getString(Intent.EXTRA_PHONE_NUMBER);
            Log.d(THIS_FILE, "Rewriter receive : " + result);

        public String getResult() {
            try {
                runSemaphore.tryAcquire(5L, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                Log.e(THIS_FILE, "Can't acquire run semaphore... problem...");
            return result;