1a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa/*
2a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * Copyright (C) 2014 The Android Open Source Project
3a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa *
4a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * Licensed under the Apache License, Version 2.0 (the "License");
5a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * you may not use this file except in compliance with the License.
6a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * You may obtain a copy of the License at
7a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa *
8a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa *      http://www.apache.org/licenses/LICENSE-2.0
9a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa *
10a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * Unless required by applicable law or agreed to in writing, software
11a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * distributed under the License is distributed on an "AS IS" BASIS,
12a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * See the License for the specific language governing permissions and
14a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * limitations under the License
15a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa */
16a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
17a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaapackage com.android.server.location;
18a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
19a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport com.android.server.ServiceWatcher;
20a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
21a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport android.content.Context;
22a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport android.hardware.location.ActivityRecognitionHardware;
236e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaaimport android.hardware.location.IActivityRecognitionHardwareClient;
24a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport android.hardware.location.IActivityRecognitionHardwareWatcher;
25a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport android.os.Handler;
266e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaaimport android.os.IBinder;
27a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport android.os.RemoteException;
28a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaaimport android.util.Log;
29a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
30a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa/**
31a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * Proxy class to bind GmsCore to the ActivityRecognitionHardware.
32a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa *
33a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa * @hide
34a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa */
35a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaapublic class ActivityRecognitionProxy {
363b0224dc3c2e7ffb93dc56970395003d0e387545destradaa    private static final String TAG = "ActivityRecognitionProxy";
373b0224dc3c2e7ffb93dc56970395003d0e387545destradaa
38a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    private final ServiceWatcher mServiceWatcher;
396e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa    private final boolean mIsSupported;
406e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa    private final ActivityRecognitionHardware mInstance;
41a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
42a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    private ActivityRecognitionProxy(
43a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            Context context,
44a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            Handler handler,
456e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa            boolean activityRecognitionHardwareIsSupported,
46a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            ActivityRecognitionHardware activityRecognitionHardware,
47a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            int overlaySwitchResId,
48a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            int defaultServicePackageNameResId,
49a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            int initialPackageNameResId) {
506e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa        mIsSupported = activityRecognitionHardwareIsSupported;
516e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa        mInstance = activityRecognitionHardware;
52a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
53a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        Runnable newServiceWork = new Runnable() {
54a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            @Override
55a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            public void run() {
566e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa                bindProvider();
57a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            }
58a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        };
59a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
60a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        // prepare the connection to the provider
61a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        mServiceWatcher = new ServiceWatcher(
62a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                context,
63a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                TAG,
64a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                "com.android.location.service.ActivityRecognitionProvider",
65a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                overlaySwitchResId,
66a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                defaultServicePackageNameResId,
67a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                initialPackageNameResId,
68a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                newServiceWork,
69a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                handler);
70a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    }
71a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
72a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    /**
73a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa     * Creates an instance of the proxy and binds it to the appropriate FusedProvider.
74a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa     *
75a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa     * @return An instance of the proxy if it could be bound, null otherwise.
76a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa     */
77a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    public static ActivityRecognitionProxy createAndBind(
78a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            Context context,
79a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            Handler handler,
806e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa            boolean activityRecognitionHardwareIsSupported,
81a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            ActivityRecognitionHardware activityRecognitionHardware,
82a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            int overlaySwitchResId,
83a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            int defaultServicePackageNameResId,
84a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            int initialPackageNameResId) {
85a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy(
86a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                context,
87a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                handler,
886e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa                activityRecognitionHardwareIsSupported,
89a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                activityRecognitionHardware,
90a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                overlaySwitchResId,
91a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                defaultServicePackageNameResId,
92a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa                initialPackageNameResId);
93a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
94a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        // try to bind the provider
95a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        if (!activityRecognitionProxy.mServiceWatcher.start()) {
963b0224dc3c2e7ffb93dc56970395003d0e387545destradaa            Log.e(TAG, "ServiceWatcher could not start.");
97a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa            return null;
98a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        }
99a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        return activityRecognitionProxy;
100a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    }
101a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa
102a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    /**
103a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa     * Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance.
104a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa     */
1056e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa    private void bindProvider() {
10666f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang        if (!mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
10766f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang            @Override
10866f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang            public void run(IBinder binder) {
10966f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                String descriptor;
11066f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                try {
11166f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    descriptor = binder.getInterfaceDescriptor();
11266f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                } catch (RemoteException e) {
11366f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    Log.e(TAG, "Unable to get interface descriptor.", e);
11466f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    return;
11566f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                }
1166e2fe75624c069bd374da65dc9d6d9ba84b4b5badestradaa
11766f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                if (IActivityRecognitionHardwareWatcher.class.getCanonicalName()
11866f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        .equals(descriptor)) {
11966f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    IActivityRecognitionHardwareWatcher watcher =
12066f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                            IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
12166f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    if (watcher == null) {
12266f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        Log.e(TAG, "No watcher found on connection.");
12366f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        return;
12466f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    }
12566f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    if (mInstance == null) {
12666f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        // to keep backwards compatibility do not update the watcher when there is
12766f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        // no instance available, or it will cause an NPE
12866f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        Log.d(TAG, "AR HW instance not available, binding will be a no-op.");
12966f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        return;
13066f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    }
13166f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    try {
13266f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        watcher.onInstanceChanged(mInstance);
13366f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    } catch (RemoteException e) {
13466f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        Log.e(TAG, "Error delivering hardware interface to watcher.", e);
13566f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    }
13666f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
13766f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                            .equals(descriptor)) {
13866f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    IActivityRecognitionHardwareClient client =
13966f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                            IActivityRecognitionHardwareClient.Stub.asInterface(binder);
14066f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    if (client == null) {
14166f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        Log.e(TAG, "No client found on connection.");
14266f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        return;
14366f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    }
14466f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    try {
14566f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        client.onAvailabilityChanged(mIsSupported, mInstance);
14666f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    } catch (RemoteException e) {
14766f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                        Log.e(TAG, "Error delivering hardware interface to client.", e);
14866f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    }
14966f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                } else {
15066f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                    Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
15166f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang                }
1523b152d95048610b77b5b53a643425a3da8141b56destradaa            }
15366f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang        })) {
15466f761c526eff2cb6115379f9b2439fe2b48d4a2Lifu Tang            Log.e(TAG, "Null binder found on connection.");
155a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa        }
156a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa    }
157a4fa3b5aa53cf677b623fe346c585cb8a0c1ce26destradaa}
158