15d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon/*
25d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * Copyright (C) 2014 The Android Open Source Project
35d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon *
45d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
55d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * you may not use this file except in compliance with the License.
65d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * You may obtain a copy of the License at
75d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon *
85d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
95d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon *
105d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * Unless required by applicable law or agreed to in writing, software
115d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
125d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * See the License for the specific language governing permissions and
145d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * limitations under the License.
155d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon */
165d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
175d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonpackage com.android.server.telecom;
185d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
195d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.content.ComponentName;
205d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.content.Context;
215d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.content.Intent;
225d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.content.ServiceConnection;
235d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.os.IBinder;
245d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.os.RemoteException;
255d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.os.ServiceManager;
265d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.os.UserHandle;
275d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport android.util.Slog;
285d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
295d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonimport com.android.server.SystemService;
305d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
315d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon/**
325d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
335d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * to run in the system-server process so once it is loaded into memory it will stay running.
345d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon * @hide
355d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon */
365d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordonpublic class TelecomLoaderService extends SystemService {
375d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private static final String TAG = "TelecomLoaderService";
385d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
395d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private class TelecomServiceConnection implements ServiceConnection {
405d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        @Override
415d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        public void onServiceConnected(ComponentName name, IBinder service) {
425d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            // Normally, we would listen for death here, but since telecom runs in the same process
435d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            // as this loader (process="system") thats redundant here.
445d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            try {
455d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                service.linkToDeath(new IBinder.DeathRecipient() {
465d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                    @Override
475d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                    public void binderDied() {
485d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                        connectToTelecom();
495d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                    }
505d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                }, 0);
515d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
525d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                ServiceManager.addService(Context.TELECOM_SERVICE, service);
535d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            } catch (RemoteException e) {
545d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon                Slog.w(TAG, "Failed linking to death.");
555d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            }
565d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        }
575d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
585d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        @Override
595d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        public void onServiceDisconnected(ComponentName name) {
605d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            connectToTelecom();
615d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        }
625d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    }
635d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
645d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private static final ComponentName SERVICE_COMPONENT = new ComponentName(
655d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            "com.android.server.telecom",
665d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            "com.android.server.telecom.TelecomService");
675d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
685d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private static final String SERVICE_ACTION = "com.android.ITelecomService";
695d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
705d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private final Context mContext;
715d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private TelecomServiceConnection mServiceConnection;
725d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
735d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    public TelecomLoaderService(Context context) {
745d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        super(context);
755d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        mContext = context;
765d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    }
775d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
785d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    @Override
795d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    public void onStart() {
805d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    }
815d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
825d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    @Override
835d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    public void onBootPhase(int phase) {
845d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        if (phase == PHASE_ACTIVITY_MANAGER_READY) {
855d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            connectToTelecom();
865d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        }
875d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    }
885d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
895d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    private void connectToTelecom() {
905d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        if (mServiceConnection != null) {
915d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            // TODO: Is unbinding worth doing or wait for system to rebind?
925d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            mContext.unbindService(mServiceConnection);
935d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            mServiceConnection = null;
945d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        }
955d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
965d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
975d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        Intent intent = new Intent(SERVICE_ACTION);
985d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        intent.setComponent(SERVICE_COMPONENT);
995d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        int flags = Context.BIND_IMPORTANT | Context.BIND_AUTO_CREATE;
1005d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon
1015d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        // Bind to Telecom and register the service
1025d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
1035d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon            mServiceConnection = serviceConnection;
1045d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon        }
1055d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon    }
1065d2c1e69ecb851121177396ac376dee1fb41d421Santos Cordon}
107