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