19dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann/*
29dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Copyright (C) 2016 The Android Open Source Project
39dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
49dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Licensed under the Apache License, Version 2.0 (the "License");
59dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * you may not use this file except in compliance with the License.
69dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * You may obtain a copy of the License at
79dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
89dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *      http://www.apache.org/licenses/LICENSE-2.0
99dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Unless required by applicable law or agreed to in writing, software
119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * distributed under the License is distributed on an "AS IS" BASIS,
129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * See the License for the specific language governing permissions and
149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * limitations under the License.
159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */
169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannpackage com.android.server.print;
189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.NonNull;
209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.Nullable;
219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.ComponentName;
229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.Context;
239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.Intent;
249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.ServiceConnection;
259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.pm.ApplicationInfo;
269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.pm.ResolveInfo;
279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.os.IBinder;
289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.os.RemoteException;
299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.os.UserHandle;
309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.printservice.recommendation.IRecommendationService;
319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.printservice.recommendation.IRecommendationServiceCallbacks;
329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.printservice.recommendation.RecommendationInfo;
339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.util.Log;
349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.internal.annotations.GuardedBy;
359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.internal.util.Preconditions;
369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport java.util.List;
389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport static android.content.pm.PackageManager.GET_META_DATA;
409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport static android.content.pm.PackageManager.GET_SERVICES;
419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann/**
449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Connection to a remote print service recommendation service.
459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */
469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannclass RemotePrintServiceRecommendationService {
479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String LOG_TAG = "RemotePrintServiceRecS";
489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Lock for this object */
509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private final Object mLock = new Object();
519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Context used for the connection */
539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private @NonNull final Context mContext;
549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**  The connection to the service (if {@link #mIsBound bound}) */
569dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    @GuardedBy("mLock")
579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private @NonNull final Connection mConnection;
589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
599dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** If the service is currently bound. */
609dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    @GuardedBy("mLock")
619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private boolean mIsBound;
629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** The service once bound */
649dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    @GuardedBy("mLock")
659dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private IRecommendationService mService;
669dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Callbacks to be called when there are updates to the print service recommendations.
699dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
709dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public interface RemotePrintServiceRecommendationServiceCallbacks {
719dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        /**
729dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann         * Called when there is an update list of print service recommendations.
739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann         *
749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann         * @param recommendations The new recommendations.
759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann         */
769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        void onPrintServiceRecommendationsUpdated(
779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                @Nullable List<RecommendationInfo> recommendations);
789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
819dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return The intent that is used to connect to the print service recommendation service.
829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private Intent getServiceIntent(@NonNull UserHandle userHandle) throws Exception {
849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        List<ResolveInfo> installedServices = mContext.getPackageManager()
859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                .queryIntentServicesAsUser(new Intent(
869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        android.printservice.recommendation.RecommendationService.SERVICE_INTERFACE),
879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING,
889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        userHandle.getIdentifier());
899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (installedServices.size() != 1) {
919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new Exception(installedServices.size() + " instead of exactly one service found");
929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        ResolveInfo installedService = installedServices.get(0);
959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        ComponentName serviceName = new ComponentName(
979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                installedService.serviceInfo.packageName,
989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                installedService.serviceInfo.name);
999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        ApplicationInfo appInfo = mContext.getPackageManager()
1019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                .getApplicationInfo(installedService.serviceInfo.packageName, 0);
1029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (appInfo == null) {
1049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new Exception("Cannot read appInfo for service");
1059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new Exception("Service is not part of the system");
1099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (!android.Manifest.permission.BIND_PRINT_RECOMMENDATION_SERVICE.equals(
1129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                installedService.serviceInfo.permission)) {
1139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new Exception("Service " + serviceName.flattenToShortString()
1149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    + " does not require permission "
1159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    + android.Manifest.permission.BIND_PRINT_RECOMMENDATION_SERVICE);
1169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        Intent serviceIntent = new Intent();
1199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        serviceIntent.setComponent(serviceName);
1209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        return serviceIntent;
1229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Open a new connection to a {@link IRecommendationService remote print service
1269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * recommendation service}.
1279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param context    The context establishing the connection
1299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param userHandle The user the connection is for
1309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param callbacks  The callbacks to call by the service
1319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    RemotePrintServiceRecommendationService(@NonNull Context context,
1339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull UserHandle userHandle,
1349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull RemotePrintServiceRecommendationServiceCallbacks callbacks) {
1359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        mContext = context;
1369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        mConnection = new Connection(callbacks);
1379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        try {
1399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            Intent serviceIntent = getServiceIntent(userHandle);
1409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            synchronized (mLock) {
1429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mIsBound = mContext.bindServiceAsUser(serviceIntent, mConnection,
1439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, userHandle);
1449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                if (!mIsBound) {
1469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    throw new Exception("Failed to bind to service " + serviceIntent);
1479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                }
1489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        } catch (Exception e) {
1509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            Log.e(LOG_TAG, "Could not connect to print service recommendation service", e);
1519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Terminate the connection to the {@link IRecommendationService remote print
1569dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * service recommendation service}.
1579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    void close() {
1599dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        synchronized (mLock) {
1609dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (mService != null) {
1619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                try {
1629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    mService.registerCallbacks(null);
1639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                } catch (RemoteException e) {
1649dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    Log.e(LOG_TAG, "Could not unregister callbacks", e);
1659dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                }
1669dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mService = null;
1689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1699dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1709dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (mIsBound) {
1719dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mContext.unbindService(mConnection);
1729dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mIsBound = false;
1739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    @Override
1789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    protected void finalize() throws Throwable {
1799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (mIsBound || mService != null) {
1809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            Log.w(LOG_TAG, "Service still connected on finalize()");
1819dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            close();
1829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        super.finalize();
1859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Connection to the service.
1899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private class Connection implements ServiceConnection {
1919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        private final RemotePrintServiceRecommendationServiceCallbacks mCallbacks;
1929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        public Connection(@NonNull RemotePrintServiceRecommendationServiceCallbacks callbacks) {
1949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            mCallbacks = callbacks;
1959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        @Override
1989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        public void onServiceConnected(ComponentName name, IBinder service) {
1999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            synchronized (mLock) {
2009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mService = (IRecommendationService)IRecommendationService.Stub.asInterface(service);
2019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                try {
2039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    mService.registerCallbacks(new IRecommendationServiceCallbacks.Stub() {
2049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        @Override
2059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        public void onRecommendationsUpdated(
2069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                List<RecommendationInfo> recommendations) {
2079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                            synchronized (mLock) {
2089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                if (mIsBound && mService != null) {
2099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                    if (recommendations != null) {
2109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                        Preconditions.checkCollectionElementsNotNull(
2119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                                recommendations, "recommendation");
2129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                    }
2139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                    mCallbacks.onPrintServiceRecommendationsUpdated(
2159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                            recommendations);
2169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                }
2179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                            }
2189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        }
2199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    });
2209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                } catch (RemoteException e) {
2219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    Log.e(LOG_TAG, "Could not register callbacks", e);
2229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                }
2239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
2249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
2259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        @Override
2279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        public void onServiceDisconnected(ComponentName name) {
2289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            Log.w(LOG_TAG, "Unexpected termination of connection");
2299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            synchronized (mLock) {
2319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mService = null;
2329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
2339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
2349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
2359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann}
236