gt:       RegistrationState state = (RegistrationState)message.obj;
context: package org.thoughtcrime.securesms;
  
  import android.app.ProgressDialog;
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.Context;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.ServiceConnection;
  import android.graphics.Color;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.os.Handler;
  import android.os.IBinder;
  import android.os.Message;
  import android.support.v7.app.AlertDialog;
  import android.text.SpannableString;
  import android.text.Spanned;
  import android.text.TextUtils;
  import android.text.method.LinkMovementMethod;
  import android.text.style.ClickableSpan;
  import android.util.Log;
  import android.view.View;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.ImageView;
  import android.widget.LinearLayout;
  import android.widget.ProgressBar;
  import android.widget.RelativeLayout;
  import android.widget.TextView;
  import android.widget.Toast;
  
  import org.thoughtcrime.securesms.crypto.MasterSecret;
  import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
  import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory;
  import org.thoughtcrime.securesms.service.MessageRetrievalService;
  import org.thoughtcrime.securesms.service.RegistrationService;
  import org.thoughtcrime.securesms.util.Dialogs;
  import org.thoughtcrime.securesms.util.TextSecurePreferences;
  import org.thoughtcrime.securesms.util.Util;
  import org.whispersystems.textsecure.api.TextSecureAccountManager;
  import org.whispersystems.textsecure.api.push.exceptions.ExpectationFailedException;
  import org.whispersystems.textsecure.api.push.exceptions.RateLimitException;
  import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
  
  import java.io.IOException;
  
  import static org.thoughtcrime.securesms.service.RegistrationService.RegistrationState;
  
  public class RegistrationProgressActivity extends BaseActionBarActivity {
  
    private static final String TAG = RegistrationProgressActivity.class.getSimpleName();
  
    private static final int FOCUSED_COLOR   = Color.parseColor("#ff333333");
    private static final int UNFOCUSED_COLOR = Color.parseColor("#ff808080");
  
    private ServiceConnection    serviceConnection        = new RegistrationServiceConnection();
    private Handler              registrationStateHandler = new RegistrationStateHandler();
    private RegistrationReceiver registrationReceiver     = new RegistrationReceiver();
  
    private RegistrationService registrationService;
  
    private LinearLayout registrationLayout;
    private LinearLayout verificationFailureLayout;
    private LinearLayout connectivityFailureLayout;
    private RelativeLayout timeoutProgressLayout;
  
    private ProgressBar registrationProgress;
    private ProgressBar connectingProgress;
    private ProgressBar verificationProgress;
    private ProgressBar generatingKeysProgress;
    private ProgressBar gcmRegistrationProgress;
  
  
    private ImageView   connectingCheck;
    private ImageView   verificationCheck;
    private ImageView   generatingKeysCheck;
    private ImageView   gcmRegistrationCheck;
  
    private TextView    connectingText;
    private TextView    verificationText;
    private TextView    registrationTimerText;
    private TextView    generatingKeysText;
    private TextView    gcmRegistrationText;
  
    private Button      verificationFailureButton;
    private Button      connectivityFailureButton;
    private Button      callButton;
    private Button      verifyButton;
  
    private EditText    codeEditText;
  
    private MasterSecret masterSecret;
    private volatile boolean visible;
  
    @Override
    public void onCreate(Bundle bundle) {
      super.onCreate(bundle);
      getSupportActionBar().setTitle(getString(R.string.RegistrationProgressActivity_verifying_number));
      setContentView(R.layout.registration_progress_activity);
  
      initializeResources();
      initializeLinks();
      initializeServiceBinding();
    }
  
    @Override
    public void onDestroy() {
      super.onDestroy();
      shutdownServiceBinding();
    }
  
    @Override
    public void onResume() {
      super.onResume();
      handleActivityVisible();
    }
  
    @Override
    public void onPause() {
      super.onPause();
      handleActivityNotVisible();
    }
  
    @Override
    public void onBackPressed() {
  
    }
  
    private void initializeServiceBinding() {
      Intent intent = new Intent(this, RegistrationService.class);
      bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }
  
    private void initializeResources() {
      this.masterSecret              = getIntent().getParcelableExtra("master_secret");
      this.registrationLayout        = (LinearLayout)findViewById(R.id.registering_layout);
      this.verificationFailureLayout = (LinearLayout)findViewById(R.id.verification_failure_layout);
      this.connectivityFailureLayout = (LinearLayout)findViewById(R.id.connectivity_failure_layout);
      this.registrationProgress      = (ProgressBar) findViewById(R.id.registration_progress);
      this.connectingProgress        = (ProgressBar) findViewById(R.id.connecting_progress);
      this.verificationProgress      = (ProgressBar) findViewById(R.id.verification_progress);
      this.generatingKeysProgress    = (ProgressBar) findViewById(R.id.generating_keys_progress);
      this.gcmRegistrationProgress   = (ProgressBar) findViewById(R.id.gcm_registering_progress);
      this.connectingCheck           = (ImageView)   findViewById(R.id.connecting_complete);
      this.verificationCheck         = (ImageView)   findViewById(R.id.verification_complete);
      this.generatingKeysCheck       = (ImageView)   findViewById(R.id.generating_keys_complete);
      this.gcmRegistrationCheck      = (ImageView)   findViewById(R.id.gcm_registering_complete);
      this.connectingText            = (TextView)    findViewById(R.id.connecting_text);
      this.verificationText          = (TextView)    findViewById(R.id.verification_text);
      this.registrationTimerText     = (TextView)    findViewById(R.id.registration_timer);
      this.generatingKeysText        = (TextView)    findViewById(R.id.generating_keys_text);
      this.gcmRegistrationText       = (TextView)    findViewById(R.id.gcm_registering_text);
      this.verificationFailureButton = (Button)      findViewById(R.id.verification_failure_edit_button);
      this.connectivityFailureButton = (Button)      findViewById(R.id.connectivity_failure_edit_button);
      this.callButton                = (Button)      findViewById(R.id.call_button);
      this.verifyButton              = (Button)      findViewById(R.id.verify_button);
      this.codeEditText              = (EditText)    findViewById(R.id.telephone_code);
      this.timeoutProgressLayout     = (RelativeLayout) findViewById(R.id.timer_progress_layout);
      Button editButton              = (Button)      findViewById(R.id.edit_button);
  
      editButton.setOnClickListener(new EditButtonListener());
      this.verificationFailureButton.setOnClickListener(new EditButtonListener());
      this.connectivityFailureButton.setOnClickListener(new EditButtonListener());
    }
  
    private void initializeLinks() {
      TextView        failureText     = (TextView) findViewById(R.id.sms_failed_text);
      RelativeLayout  smsAlertLayout  = (RelativeLayout) findViewById(R.id.sms_alert_layout);
      String          pretext         = getString(R.string.registration_progress_activity__signal_timed_out_while_waiting_for_a_verification_sms_message);
      String          link            = getString(R.string.RegistrationProblemsActivity_possible_problems);
      SpannableString spannableString = new SpannableString(pretext + " " + link);
  
      spannableString.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
          new AlertDialog.Builder(RegistrationProgressActivity.this)
                  .setTitle(R.string.RegistrationProblemsActivity_possible_problems)
                  .setView(R.layout.registration_problems)
                  .setNeutralButton(android.R.string.ok, null)
                  .show();
        }
      }, pretext.length() + 1, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  
      failureText.setText(spannableString);
      failureText.setMovementMethod(LinkMovementMethod.getInstance());
      if (android.os.Build.BRAND.toLowerCase().contains("blackberry")) {
        smsAlertLayout.setVisibility(View.GONE);
      }
    }
  
    private void handleActivityVisible() {
      IntentFilter filter = new IntentFilter(RegistrationService.REGISTRATION_EVENT);
      filter.setPriority(1000);
      registerReceiver(registrationReceiver, filter);
      visible = true;
    }
  
    private void handleActivityNotVisible() {
      unregisterReceiver(registrationReceiver);
      visible = false;
    }
  
    private void handleStateIdle() {
      if (hasNumberDirective()) {
        Intent intent = new Intent(this, RegistrationService.class);
        intent.setAction(RegistrationService.REGISTER_NUMBER_ACTION);
        intent.putExtra("e164number", getNumberDirective());
        intent.putExtra("master_secret", masterSecret);
        startService(intent);
      } else {
        Intent intent = new Intent(this, RegistrationActivity.class);
        intent.putExtra("master_secret", masterSecret);
        startActivity(intent);
        finish();
      }
    }
  
    private void handleStateConnecting() {
      this.registrationLayout.setVisibility(View.VISIBLE);
      this.verificationFailureLayout.setVisibility(View.GONE);
      this.connectivityFailureLayout.setVisibility(View.GONE);
      this.connectingProgress.setVisibility(View.VISIBLE);
      this.connectingCheck.setVisibility(View.INVISIBLE);
      this.verificationProgress.setVisibility(View.INVISIBLE);
      this.verificationCheck.setVisibility(View.INVISIBLE);
      this.generatingKeysProgress.setVisibility(View.INVISIBLE);
      this.generatingKeysCheck.setVisibility(View.INVISIBLE);
      this.gcmRegistrationProgress.setVisibility(View.INVISIBLE);
      this.gcmRegistrationCheck.setVisibility(View.INVISIBLE);
      this.connectingText.setTextColor(FOCUSED_COLOR);
      this.verificationText.setTextColor(UNFOCUSED_COLOR);
      this.generatingKeysText.setTextColor(UNFOCUSED_COLOR);
      this.gcmRegistrationText.setTextColor(UNFOCUSED_COLOR);
      this.timeoutProgressLayout.setVisibility(View.VISIBLE);
    }
  
    private void handleStateVerifying() {
      this.registrationLayout.setVisibility(View.VISIBLE);
      this.verificationFailureLayout.setVisibility(View.GONE);
      this.connectivityFailureLayout.setVisibility(View.GONE);
      this.connectingProgress.setVisibility(View.INVISIBLE);
      this.connectingCheck.setVisibility(View.VISIBLE);
      this.verificationProgress.setVisibility(View.VISIBLE);
      this.verificationCheck.setVisibility(View.INVISIBLE);
      this.generatingKeysProgress.setVisibility(View.INVISIBLE);
      this.generatingKeysCheck.setVisibility(View.INVISIBLE);
      this.gcmRegistrationProgress.setVisibility(View.INVISIBLE);
      this.gcmRegistrationCheck.setVisibility(View.INVISIBLE);
      this.connectingText.setTextColor(UNFOCUSED_COLOR);
      this.verificationText.setTextColor(FOCUSED_COLOR);
      this.generatingKeysText.setTextColor(UNFOCUSED_COLOR);
      this.gcmRegistrationText.setTextColor(UNFOCUSED_COLOR);
      this.registrationProgress.setVisibility(View.VISIBLE);
      this.timeoutProgressLayout.setVisibility(View.VISIBLE);
    }
  
    private void handleStateGeneratingKeys() {
      this.registrationLayout.setVisibility(View.VISIBLE);
      this.verificationFailureLayout.setVisibility(View.GONE);
      this.connectivityFailureLayout.setVisibility(View.GONE);
      this.connectingProgress.setVisibility(View.INVISIBLE);
      this.connectingCheck.setVisibility(View.VISIBLE);
      this.verificationProgress.setVisibility(View.INVISIBLE);
      this.verificationCheck.setVisibility(View.VISIBLE);
      this.generatingKeysProgress.setVisibility(View.VISIBLE);
      this.generatingKeysCheck.setVisibility(View.INVISIBLE);
      this.gcmRegistrationProgress.setVisibility(View.INVISIBLE);
      this.gcmRegistrationCheck.setVisibility(View.INVISIBLE);
      this.connectingText.setTextColor(UNFOCUSED_COLOR);
      this.verificationText.setTextColor(UNFOCUSED_COLOR);
      this.generatingKeysText.setTextColor(FOCUSED_COLOR);
      this.gcmRegistrationText.setTextColor(UNFOCUSED_COLOR);
      this.registrationProgress.setVisibility(View.INVISIBLE);
      this.timeoutProgressLayout.setVisibility(View.INVISIBLE);
    }
  
    private void handleStateGcmRegistering() {
      this.registrationLayout.setVisibility(View.VISIBLE);
      this.verificationFailureLayout.setVisibility(View.GONE);
      this.connectivityFailureLayout.setVisibility(View.GONE);
      this.connectingProgress.setVisibility(View.INVISIBLE);
      this.connectingCheck.setVisibility(View.VISIBLE);
      this.verificationProgress.setVisibility(View.INVISIBLE);
      this.verificationCheck.setVisibility(View.VISIBLE);
      this.generatingKeysProgress.setVisibility(View.INVISIBLE);
      this.generatingKeysCheck.setVisibility(View.VISIBLE);
      this.gcmRegistrationProgress.setVisibility(View.VISIBLE);
      this.gcmRegistrationCheck.setVisibility(View.INVISIBLE);
      this.connectingText.setTextColor(UNFOCUSED_COLOR);
      this.verificationText.setTextColor(UNFOCUSED_COLOR);
      this.generatingKeysText.setTextColor(UNFOCUSED_COLOR);
      this.gcmRegistrationText.setTextColor(FOCUSED_COLOR);
      this.registrationProgress.setVisibility(View.INVISIBLE);
      this.timeoutProgressLayout.setVisibility(View.INVISIBLE);
    }
  
    private void handleGcmTimeout(RegistrationState state) {
      handleConnectivityError(state);
    }
  
    private void handleVerificationRequestedVoice(RegistrationState state) {
      handleVerificationTimeout(state);
      verifyButton.setOnClickListener(new VerifyClickListener(state.number, state.password));
      verifyButton.setEnabled(true);
      codeEditText.setEnabled(true);
    }
  
    private void handleVerificationTimeout(RegistrationState state) {
      this.callButton.setOnClickListener(new CallClickListener(state.number));
      this.verifyButton.setEnabled(false);
      this.codeEditText.setEnabled(false);
      this.registrationLayout.setVisibility(View.GONE);
      this.connectivityFailureLayout.setVisibility(View.GONE);
      this.verificationFailureLayout.setVisibility(View.VISIBLE);
      this.verificationFailureButton.setText(String.format(getString(R.string.RegistrationProgressActivity_edit_s),
                                                           PhoneNumberFormatter.formatNumberInternational(state.number)));
    }
  
    private void handleConnectivityError(RegistrationState state) {
      this.registrationLayout.setVisibility(View.GONE);
      this.verificationFailureLayout.setVisibility(View.GONE);
      this.connectivityFailureLayout.setVisibility(View.VISIBLE);
      this.connectivityFailureButton.setText(String.format(getString(R.string.RegistrationProgressActivity_edit_s),
                                                           PhoneNumberFormatter.formatNumberInternational(state.number)));
    }
  
    private void handleMultiRegistrationError(RegistrationState state) {
      handleVerificationTimeout(state);
      Dialogs.showAlertDialog(this,                         getString(R.string.RegistrationProgressActivity_registration_conflict),
                           getString(R.string.RegistrationProgressActivity_this_number_is_already_registered_on_a_different));
    }
  
    private void handleVerificationComplete() {
      if (visible) {
        Toast.makeText(this,
                       R.string.RegistrationProgressActivity_registration_complete,
                       Toast.LENGTH_LONG).show();
      }
  
      shutdownService();
      ApplicationContext.getInstance(this).getJobManager().add(new PushNotificationReceiveJob(this));
      finish();
    }
  
    private void handleTimerUpdate() {
      if (registrationService == null)
        return;
  
      int totalSecondsRemaining = registrationService.getSecondsRemaining();
      int minutesRemaining      = totalSecondsRemaining / 60;
      int secondsRemaining      = totalSecondsRemaining - (minutesRemaining * 60);
      double percentageComplete = (double)((60 * 2) - totalSecondsRemaining) / (double)(60 * 2);
      int progress              = (int)Math.round(((double)registrationProgress.getMax()) * percentageComplete);
  
      this.registrationProgress.setProgress(progress);
      this.registrationTimerText.setText(String.format("%02d:%02d", minutesRemaining, secondsRemaining));
  
      registrationStateHandler.sendEmptyMessageDelayed(RegistrationState.STATE_TIMER, 1000);
    }
  
    private boolean hasNumberDirective() {
      return getIntent().getStringExtra("e164number") != null;
    }
  
    private String getNumberDirective() {
      return getIntent().getStringExtra("e164number");
    }
  
    private void shutdownServiceBinding() {
      if (serviceConnection != null) {
        unbindService(serviceConnection);
        serviceConnection = null;
      }
    }
  
    private void shutdownService() {
      if (registrationService != null) {
        registrationService.shutdown();
        registrationService = null;
      }
  
      shutdownServiceBinding();
  
      Intent serviceIntent = new Intent(RegistrationProgressActivity.this, RegistrationService.class);
      stopService(serviceIntent);
    }
  
    private class RegistrationServiceConnection implements ServiceConnection {
      @Override
      public void onServiceConnected(ComponentName className, IBinder service) {
        registrationService  = ((RegistrationService.RegistrationServiceBinder)service).getService();
        registrationService.setRegistrationStateHandler(registrationStateHandler);
  
        RegistrationState state = registrationService.getRegistrationState();
        registrationStateHandler.obtainMessage(state.state, state).sendToTarget();
  
        handleTimerUpdate();
      }
  
      @Override
      public void onServiceDisconnected(ComponentName name) {
        registrationService.setRegistrationStateHandler(null);
      }
    }
  
    private class RegistrationStateHandler extends Handler {
      @Override
      public void handleMessage(Message message) {
  