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.Context;
  import android.database.Cursor;
  import android.net.Uri;
  import android.util.Log;
  
  import java.lang.reflect.Method;
  
  /**
   * 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.
   */
  public class AttributionIdentifiers {
      private static final String TAG = AttributionIdentifiers.class.getCanonicalName();
      private static final Uri ATTRIBUTION_ID_CONTENT_URI =
              Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider");
      private static final String ATTRIBUTION_ID_COLUMN_NAME = "aid";
      private static final String ANDROID_ID_COLUMN_NAME = "androidid";
      private static final String LIMIT_TRACKING_COLUMN_NAME = "limit_tracking";
  
      // com.google.android.gms.common.ConnectionResult.SUCCESS
      private static final int CONNECTION_RESULT_SUCCESS = 0;
  
      private static final long IDENTIFIER_REFRESH_INTERVAL_MILLIS = 3600 * 1000;
  
      private String attributionId;
      private String androidAdvertiserId;
      private boolean limitTracking;
      private long fetchTime;
  
      private static AttributionIdentifiers recentlyFetchedIdentifiers;
  
      private static AttributionIdentifiers getAndroidId(Context context) {
          AttributionIdentifiers identifiers = new AttributionIdentifiers();
          try {
              Method isGooglePlayServicesAvailable = Utility.getMethodQuietly(
                      "com.google.android.gms.common.GooglePlayServicesUtil",
                      "isGooglePlayServicesAvailable",
                      Context.class
              );
  
              if (isGooglePlayServicesAvailable == null) {
                  return identifiers;
              }
  
              Object connectionResult = Utility.invokeMethodQuietly(null, isGooglePlayServicesAvailable, context);
              if (!(connectionResult instanceof Integer) || (Integer) connectionResult != CONNECTION_RESULT_SUCCESS) {
                  return identifiers;
              }
  
              Method getAdvertisingIdInfo = Utility.getMethodQuietly(
                      "com.google.android.gms.ads.identifier.AdvertisingIdClient",
                      "getAdvertisingIdInfo",
                      Context.class
              );
              if (getAdvertisingIdInfo == null) {
                  return identifiers;
              }
              Object advertisingInfo = Utility.invokeMethodQuietly(null, getAdvertisingIdInfo, context);
              if (advertisingInfo == null) {
                  return identifiers;
              }
  
              Method getId = Utility.getMethodQuietly(advertisingInfo.getClass(), "getId");
              Method isLimitAdTrackingEnabled = Utility.getMethodQuietly(advertisingInfo.getClass(), "isLimitAdTrackingEnabled");
              if (getId == null || isLimitAdTrackingEnabled == null) {
                  return identifiers;
              }
  
              identifiers.androidAdvertiserId = (String) Utility.invokeMethodQuietly(advertisingInfo, getId);
              identifiers.limitTracking = (Boolean) Utility.invokeMethodQuietly(advertisingInfo, isLimitAdTrackingEnabled);
          } catch (Exception e) {
              Utility.logd("android_id", e);
          }
          return identifiers;
      }
  
      public static AttributionIdentifiers getAttributionIdentifiers(Context context) {
          if (recentlyFetchedIdentifiers != null &&
              System.currentTimeMillis() - recentlyFetchedIdentifiers.fetchTime < IDENTIFIER_REFRESH_INTERVAL_MILLIS) {
              return recentlyFetchedIdentifiers;
          }
  
          AttributionIdentifiers identifiers = getAndroidId(context);
  
          try {
              String [] projection = {ATTRIBUTION_ID_COLUMN_NAME, ANDROID_ID_COLUMN_NAME, LIMIT_TRACKING_COLUMN_NAME};
              Cursor c = context.getContentResolver().query(ATTRIBUTION_ID_CONTENT_URI, projection, null, null, null);
              if (c == null || !c.moveToFirst()) {
                  return null;
              }
              int attributionColumnIndex = c.getColumnIndex(ATTRIBUTION_ID_COLUMN_NAME);
              int androidIdColumnIndex = c.getColumnIndex(ANDROID_ID_COLUMN_NAME);
              int limitTrackingColumnIndex = c.getColumnIndex(LIMIT_TRACKING_COLUMN_NAME);
  
              identifiers.attributionId = c.getString(attributionColumnIndex);
  
              // if we failed to call Google's APIs directly (due to improper integration by the client), it may be
              // possible for the local facebook application to relay it to us.
              if (androidIdColumnIndex > 0 && limitTrackingColumnIndex > 0 && identifiers.getAndroidAdvertiserId() == null) {
                  identifiers.androidAdvertiserId = c.getString(androidIdColumnIndex);
                  identifiers.limitTracking = Boolean.parseBoolean(c.getString(limitTrackingColumnIndex));
              }
              c.close();
          } catch (Exception e) {
              Log.d(TAG, "Caught unexpected exception in getAttributionId(): " + e.toString());
              return null;
          }
  
          identifiers.fetchTime = System.currentTimeMillis();
          recentlyFetchedIdentifiers = identifiers;
          return identifiers;
      }
  
      public String getAttributionId() {
          return attributionId;
      }
  
      public String getAndroidAdvertiserId() {
          return androidAdvertiserId;
      }
  
      public boolean isTrackingLimited() {
          return limitTracking;
      }
  }