content: /**
   * Copyright 2010-present Facebook.
   *
   * 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.facebook.internal;
  
  import android.content.ComponentName;
  import android.content.Context;
  import android.content.Intent;
  import android.content.ServiceConnection;
  import android.os.*;
  
  /**
   * com.facebook.internal is solely for the use of other packages within the Facebook SDK for Android. Use of
   * any of the classes in this package is unsupported, and they may be modified or removed without warning at
   * any time.
   */
  abstract public class PlatformServiceClient implements ServiceConnection {
      private final Context context;
      private final Handler handler;
      private CompletedListener listener;
      private boolean running;
      private Messenger sender;
      private int requestMessage;
      private int replyMessage;
      private final String applicationId;
      private final int protocolVersion;
  
      public PlatformServiceClient(Context context, int requestMessage, int replyMessage, int protocolVersion,
              String applicationId) {
          Context applicationContext = context.getApplicationContext();
  
          this.context = (applicationContext != null) ? applicationContext : context;
          this.requestMessage = requestMessage;
          this.replyMessage = replyMessage;
          this.applicationId = applicationId;
          this.protocolVersion = protocolVersion;
  
          handler = new Handler() {
              @Override
              public void handleMessage(Message message) {
                  PlatformServiceClient.this.handleMessage(message);
              }
          };
      }
  
      public void setCompletedListener(CompletedListener listener) {
          this.listener = listener;
      }
  
      protected Context getContext() {
          return context;
      }
  
      public boolean start() {
          if (running) {
              return false;
          }
  
          // Make sure that the service can handle the requested protocol version
          int availableVersion = NativeProtocol.getLatestAvailableProtocolVersionForService(context, protocolVersion);
          if (availableVersion == NativeProtocol.NO_PROTOCOL_AVAILABLE) {
              return false;
          }
  
          Intent intent = NativeProtocol.createPlatformServiceIntent(context);
          if (intent == null) {
              return false;
          } else {
              running = true;
              context.bindService(intent, this, Context.BIND_AUTO_CREATE);
              return true;
          }
      }
  
      public void cancel() {
          running = false;
      }
  
      public void onServiceConnected(ComponentName name, IBinder service) {
          sender = new Messenger(service);
          sendMessage();
      }
  
      public void onServiceDisconnected(ComponentName name) {
          sender = null;
          context.unbindService(this);
          callback(null);
      }
  
      private void sendMessage() {
          Bundle data = new Bundle();
          data.putString(NativeProtocol.EXTRA_APPLICATION_ID, applicationId);
  
          populateRequestBundle(data);
  
          Message request = Message.obtain(null, requestMessage);
          request.arg1 = protocolVersion;
          request.setData(data);
          request.replyTo = new Messenger(handler);
  
          try {
              sender.send(request);
          } catch (RemoteException e) {
              callback(null);
          }
      }
  
      protected abstract void populateRequestBundle(Bundle data);
  
      protected void handleMessage(Message message) {
          if (message.what == replyMessage) {
              Bundle extras = message.getData();
              String errorType = extras.getString(NativeProtocol.STATUS_ERROR_TYPE);
              if (errorType != null) {
                  callback(null);
              } else {
                  callback(extras);
              }
              context.unbindService(this);
          }
      }
  
      private void callback(Bundle result) {
          if (!running) {
              return;
          }
          running = false;
  
          CompletedListener callback = listener;
          if (callback != null) {
              callback.completed(result);
          }
      }
  
      public interface CompletedListener {
          void completed(Bundle result);
      }
  }
  