All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.internal.telephony.ims.ImsServiceFeatureQueryManager Maven / Gradle / Ivy

/*
 * Copyright (C) 2018 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.
 */

package com.android.internal.telephony.ims;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.telephony.ims.aidl.IImsServiceController;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.util.Log;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Manages the querying of multiple ImsServices asynchronously in order to retrieve the ImsFeatures
 * they support.
 */

public class ImsServiceFeatureQueryManager {

    private final class ImsServiceFeatureQuery implements ServiceConnection {

        private static final String LOG_TAG = "ImsServiceFeatureQuery";

        private final ComponentName mName;
        private final String mIntentFilter;

        ImsServiceFeatureQuery(ComponentName name, String intentFilter) {
            mName = name;
            mIntentFilter = intentFilter;
        }

        /**
         * Starts the bind to the ImsService specified ComponentName.
         * @return true if binding started, false if it failed and will not recover.
         */
        public boolean start() {
            Log.d(LOG_TAG, "start: intent filter=" + mIntentFilter + ", name=" + mName);
            Intent imsServiceIntent = new Intent(mIntentFilter).setComponent(mName);
            int serviceFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                    | Context.BIND_IMPORTANT;
            boolean bindStarted = mContext.bindService(imsServiceIntent, this, serviceFlags);
            if (!bindStarted) {
                // Docs say to unbind if this fails.
                cleanup();
            }
            return bindStarted;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(LOG_TAG, "onServiceConnected for component: " + name);
            if (service != null) {
                queryImsFeatures(IImsServiceController.Stub.asInterface(service));
            } else {
                Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null, cleaning up.");
                cleanup();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.w(LOG_TAG, "onServiceDisconnected for component: " + name);
        }

        private void queryImsFeatures(IImsServiceController controller) {
            ImsFeatureConfiguration config;
            try {
                config = controller.querySupportedImsFeatures();
            } catch (Exception e) {
                Log.w(LOG_TAG, "queryImsFeatures - error: " + e);
                cleanup();
                mListener.onError(mName);
                return;
            }
            Set servicePairs = config.getServiceFeatures();
            // Complete, remove from active queries and notify.
            cleanup();
            mListener.onComplete(mName, servicePairs);
        }

        private void cleanup() {
            mContext.unbindService(this);
            synchronized (mLock) {
                mActiveQueries.remove(mName);
            }
        }
    }

    public interface Listener {
        /**
         * Called when a query has completed.
         * @param name The Package Name of the query
         * @param features A Set of slotid->feature pairs that the ImsService supports.
         */
        void onComplete(ComponentName name, Set features);

        /**
         * Called when a query has failed and should be retried.
         */
        void onError(ComponentName name);
    }

    // Maps an active ImsService query (by Package Name String) its query.
    private final Map mActiveQueries = new HashMap<>();
    private final Context mContext;
    private final Listener mListener;
    private final Object mLock = new Object();

    public ImsServiceFeatureQueryManager(Context context, Listener listener) {
        mContext = context;
        mListener = listener;
    }

    /**
     * Starts an ImsService feature query for the ComponentName and Intent specified.
     * @param name The ComponentName of the ImsService being queried.
     * @param intentFilter The Intent filter that the ImsService specified.
     * @return true if the query started, false if it was unable to start.
     */
    public boolean startQuery(ComponentName name, String intentFilter) {
        synchronized (mLock) {
            if (mActiveQueries.containsKey(name)) {
                // We already have an active query, wait for it to return.
                return true;
            }
            ImsServiceFeatureQuery query = new ImsServiceFeatureQuery(name, intentFilter);
            mActiveQueries.put(name, query);
            return query.start();
        }
    }

    /**
     * @return true if there are any active queries, false if the manager is idle.
     */
    public boolean isQueryInProgress() {
        synchronized (mLock) {
            return !mActiveQueries.isEmpty();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy