text:
package gpio

import (
	"errors"
	"testing"

	"github.com/hybridgroup/gobot"
	"github.com/hybridgroup/gobot/gobottest"
)

var _ gobot.Driver = (*RgbLedDriver)(nil)

func initTestRgbLedDriver(conn DigitalWriter) *RgbLedDriver {
	testAdaptorDigitalWrite = func() (err error) {
		return nil
	}
	testAdaptorPwmWrite = func() (err error) {
		return nil
	}
	return NewRgbLedDriver(conn, "bot", "1", "2", "3")
}

func TestRgbLedDriver(t *testing.T) {
	var err interface{}

	d := initTestRgbLedDriver(newGpioTestAdaptor("adaptor"))

	gobottest.Assert(t, d.Name(), "bot")
	gobottest.Assert(t, d.Pin(), "r=1, g=2, b=3")
	gobottest.Assert(t, d.RedPin(), "1")
	gobottest.Assert(t, d.GreenPin(), "2")
	gobottest.Assert(t, d.BluePin(), "3")
	gobottest.Assert(t, d.Connection().Name(), "adaptor")

	testAdaptorDigitalWrite = func() (err error) {
		return errors.New("write error")
	}
	testAdaptorPwmWrite = func() (err error) {
		return errors.New("pwm error")
	}

	err = d.Command("Toggle")(nil)
	gobottest.Assert(t, err.(error), errors.New("pwm error"))

	err = d.Command("On")(nil)
	gobottest.Assert(t, err.(error), errors.New("pwm error"))

	err = d.Command("Off")(nil)
	gobottest.Assert(t, err.(error), errors.New("pwm error"))

	err = d.Command("SetRGB")(map[string]interface{}{"r": 0xff, "g": 0xff, "b": 0xff})
	gobottest.Assert(t, err.(error), errors.New("pwm error"))

}

func TestRgbLedDriverStart(t *testing.T) {
	d := initTestRgbLedDriver(newGpioTestAdaptor("adaptor"))
	gobottest.Assert(t, len(d.Start()), 0)
}

func TestRgbLedDriverHalt(t *testing.T) {
	d := initTestRgbLedDriver(newGpioTestAdaptor("adaptor"))
	gobottest.Assert(t, len(d.Halt()), 0)
}

func TestRgbLedDriverToggle(t *testing.T) {
	d := initTestRgbLedDriver(newGpioTestAdaptor("adaptor"))
	d.Off()
	d.Toggle()
	gobottest.Assert(t, d.State(), true)
	d.Toggle()
	gobottest.Assert(t, d.State(), false)
}

func TestRgbLedDriverSetLevel(t *testing.T) {
	d := initTestRgbLedDriver(&gpioTestDigitalWriter{})
	gobottest.Assert(t, d.SetLevel("1", 150), ErrPwmWriteUnsupported)

	d = initTestRgbLedDriver(newGpioTestAdaptor("adaptor"))
	testAdaptorPwmWrite = func() (err error) {
		err = errors.New("pwm error")
		return
	}
	gobottest.Assert(t, d.SetLevel("1", 150), errors.New("pwm error"))
}

redpajama_set_name: RedPajamaGithub


text:
title: Technical Articles
type: docs
weight: 30
url: /net/technical-articles/
---


text:
;(function() {

	window.jsPlumbDemo = {

		init : function() {

			jsPlumb.importDefaults({
				Connector:"StateMachine",
				PaintStyle:{ lineWidth:3, strokeStyle:"#ffa500", "dashstyle":"2 4" },
				Endpoint:[ "Dot", { radius:5 } ],
				EndpointStyle:{ fillStyle:"#ffa500" }
			});

			var shapes = $(".shape");

			// make everything draggable
			jsPlumb.draggable(shapes);

			// loop through them and connect each one to each other one.
			for (var i = 0; i < shapes.length; i++) {
				for (var j = i + 1; j < shapes.length; j++) {
					jsPlumb.connect({
						source:shapes[i],  // just pass in the current node in the selector for source
						target:shapes[j],
						// here we supply a different anchor for source and for target, and we get the element's "data-shape"
						// attribute to tell us what shape we should use, as well as, optionally, a rotation value.
						anchors:[
							[ "Perimeter", { shape:$(shapes[i]).attr("data-shape"), rotation:$(shapes[i]).attr("data-rotation") }],
							[ "Perimeter", { shape:$(shapes[j]).attr( "data-shape"), rotation:$(shapes[j]).attr("data-rotation") }]
						]
					});
				}
			}
    }
  }

})();


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

	<title>CKFinder User's Guide</title>
	<link href="../../files/other/help.css" type="text/css" rel="stylesheet" />

	<meta name="robots" content="noindex, nofollow" />

		Upload Button

		The Upload button that is available in the CKFinder
		Toolbar opens the
		Upload Pane which you can use to add new files to the
		current folder.

The figure below presents the default file browser Upload Pane
		that is expanded when you click the toolbar button.

		In order to close (collapse) the Upload Pane, press
		the Cancel button (if you have not started the upload process yet)
		or the Close button (if the upload has already finished). You can
		also click the Upload toolbar button once again to collapse the panel.

		Note: Upload is a technical term that
		stands for the action of sending the files from your local computer to a central
		computer (also known as a server).

		Upload Pane Versions

CKFinder Upload Pane comes in two flavors, depending on your
		environment. By default, the multiple upload solution (that lets you send more
		files to the server in one operation) is used for all environments that support
		Adobe Flash. If, however, your local system does not support Flash, you will
		still be able to upload individual files in separate operations thanks to the
		fallback solution.

The figure above presents the default Upload Pane with multiple
		upload solution enabled. For all systems that do not support Flash (including
		some mobile browsers) the following Upload Pane format will
		be used.

		Multiple File Upload

		By default CKFinder will allow you to upload multiple files at the same time.
		In order to send the files to the server, follow the steps described below.

Step 1: Click the Upload toolbar button to open the
		Upload Pane.

Step 2: When the Upload Pane expands, choose the
		Add Files button. A native file selection dialog window of
		your operating system that opens will let you choose the local file to be
		uploaded to the server.

Note: You can choose as many files as you want by
		selecting them in the dialog window all at once.

Step 3: The local file(s) will now be added to the upload queue.
		If you want to add further files to this upload batch, click the
		Add Files button again and repeat the steps described above.

Step 4: If you change your mind about the files that should be sent to the server, you
		can always either remove individual files from the upload queue by clicking
		the Remove button next to the file, or decide to cancel the whole
		upload process by choosing the Cancel button of the
		Upload Pane.

Step 5: If you are ready with the file selection process, you can click the
		Upload button to start the upload. The progress of the whole process
		as well as individual files can be observed on the screen.

Step 6: Wait for the upload to terminate. Once it is completed, the folder
		content will refresh and the uploaded file (or the last one of the multiple files)
		will be selected in the Files Pane.

		Single File Upload

When Adobe Flash is not available in your system, CKFinder upload will be fully
		functional, though limited to uploading one file at a time. In order to send the
		file to the server, follow the steps described below.

Step 1: Click the Upload toolbar button to open the
		Upload Pane.

Step 2: When the Upload Pane expands, choose the
		Browse button.	A native file selection dialog window of your
		operating system that opens will let you choose the local file to be uploaded
		to the server.

Note: The button caption may differ between browsers.

Step 3: The local file will now be selected. You can only upload one file
		at a time.

Step 4: If you are ready with the file selection process, you can click the
		Upload Selected File button to start the upload. The progress of the
		file upload process can be observed on the screen.

Step 5: Wait for the upload to terminate. Once it is completed, the
		Upload Pane will be closed, the folder content will refresh, and the uploaded
		 file will be selected in the Files Pane.

		Upload Errors

		The following error messages  may appear when uploading files.

		A file with the same name is already available. The uploaded file was renamed
		to "filename(1).ext"

		This message indicates that the uploaded file name is already in use by another
		file in the same folder. To avoid conflict, a consecutive number, the "(1)", was
		appended to the original name.

		Invalid file

		The file that you attempted to upload was not accepted.

		The most common cause for this message is that CKFinder was configured to not
		accept the kind of file you are trying to upload based on its extension. This
		is a security restriction. It is also possible that the file size is too
		large for your system. If this is the case, the server must be configured to
		accept bigger files.

Upload cancelled for security reasons. The file contains HTML-like data.

The uploaded file contains HTML code. For security reasons, only files with selected
		extensions are allowed to contain HTML code.

		Please contact your system administrator to get more information regarding the
		accepted file types and their size limits.


text:
if(DEFINED POLLY_GCC_32BIT_CXX14_PIC_CMAKE_)
  return()
else()
  set(POLLY_GCC_32BIT_CXX14_PIC_CMAKE_ 1)
endif()

include("${CMAKE_CURRENT_LIST_DIR}/utilities/polly_init.cmake")

polly_init(
    "gcc / 32-bit / c++14 support / PIC"
    "Unix Makefiles"
)

include("${CMAKE_CURRENT_LIST_DIR}/utilities/polly_common.cmake")

include("${CMAKE_CURRENT_LIST_DIR}/compiler/gcc.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/flags/cxx14.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/flags/cxx11-abi-disable.cmake") # effectively forced to 0 on RH7 and centos7, so disable to be consistent
include("${CMAKE_CURRENT_LIST_DIR}/flags/fpic.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/flags/32bit.cmake")


text:
.class public final Lcom/android/internal/telephony/uicc/IsimUiccRecords;
.super Lcom/android/internal/telephony/uicc/IccRecords;
.source "IsimUiccRecords.java"

# interfaces
.implements Lcom/android/internal/telephony/uicc/IsimRecords;

# annotations
.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;,
        Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;,
        Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;,
        Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;,
        Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;
    }
.end annotation

# static fields
.field private static final DBG:Z = true

.field private static final DUMP_RECORDS:Z = false

.field private static final EVENT_AKA_AUTHENTICATE_DONE:I = 0x5a

.field private static final EVENT_APP_READY:I = 0x1

.field private static final EVENT_ISIM_REFRESH:I = 0x1f

.field public static final INTENT_ISIM_REFRESH:Ljava/lang/String; = "com.android.intent.isim_refresh"

.field protected static final LOG_TAG:Ljava/lang/String; = "IsimUiccRecords"

.field private static final TAG_ISIM_VALUE:I = 0x80

# instance fields
.field private auth_rsp:Ljava/lang/String;

.field private mIsimDomain:Ljava/lang/String;

.field private mIsimImpi:Ljava/lang/String;

.field private mIsimImpu:[Ljava/lang/String;

.field private mIsimIst:Ljava/lang/String;

.field private mIsimPcscf:[Ljava/lang/String;

.field private final mLock:Ljava/lang/Object;

# direct methods
.method static synthetic -get0(Lcom/android/internal/telephony/uicc/IsimUiccRecords;)[Ljava/lang/String;
    .locals 1

    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;

    return-object v0
.end method

.method static synthetic -get1(Lcom/android/internal/telephony/uicc/IsimUiccRecords;)[Ljava/lang/String;
    .locals 1

    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;

    return-object v0
.end method

.method static synthetic -set0(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Ljava/lang/String;)Ljava/lang/String;
    .locals 0

    iput-object p1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimDomain:Ljava/lang/String;

    return-object p1
.end method

.method static synthetic -set1(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Ljava/lang/String;)Ljava/lang/String;
    .locals 0

    iput-object p1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpi:Ljava/lang/String;

    return-object p1
.end method

.method static synthetic -set2(Lcom/android/internal/telephony/uicc/IsimUiccRecords;[Ljava/lang/String;)[Ljava/lang/String;
    .locals 0

    iput-object p1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;

    return-object p1
.end method

.method static synthetic -set3(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Ljava/lang/String;)Ljava/lang/String;
    .locals 0

    iput-object p1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimIst:Ljava/lang/String;

    return-object p1
.end method

.method static synthetic -set4(Lcom/android/internal/telephony/uicc/IsimUiccRecords;[Ljava/lang/String;)[Ljava/lang/String;
    .locals 0

    iput-object p1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;

    return-object p1
.end method

.method static synthetic -wrap0([B)Ljava/lang/String;
    .locals 1
    .param p0, "record"    # [B

    .prologue
    invoke-static {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->isimTlvToString([B)Ljava/lang/String;

    move-result-object v0

    return-object v0
.end method

.method public constructor <init>(Lcom/android/internal/telephony/uicc/UiccCardApplication;Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;)V
    .locals 3
    .param p1, "app"    # Lcom/android/internal/telephony/uicc/UiccCardApplication;
    .param p2, "c"    # Landroid/content/Context;
    .param p3, "ci"    # Lcom/android/internal/telephony/CommandsInterface;

    .prologue
    const/4 v2, 0x0

    const/4 v1, 0x0

    .line 81
    invoke-direct {p0, p1, p2, p3}, Lcom/android/internal/telephony/uicc/IccRecords;-><init>(Lcom/android/internal/telephony/uicc/UiccCardApplication;Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;)V

    .line 66
    new-instance v0, Ljava/lang/Object;

    invoke-direct {v0}, Ljava/lang/Object;-><init>()V

    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;

    .line 83
    iput-boolean v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsRequested:Z

    .line 86
    iput v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 88
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->resetRecords()V

    .line 89
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mCi:Lcom/android/internal/telephony/CommandsInterface;

    const/16 v1, 0x1f

    invoke-interface {v0, p0, v1, v2}, Lcom/android/internal/telephony/CommandsInterface;->registerForIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V

    .line 91
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;

    const/4 v1, 0x1

    invoke-virtual {v0, p0, v1, v2}, Lcom/android/internal/telephony/uicc/UiccCardApplication;->registerForReady(Landroid/os/Handler;ILjava/lang/Object;)V

    .line 92
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v1, "IsimUiccRecords X ctor this="

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 80
    return-void
.end method

.method private handleFileUpdate(I)V
    .locals 4
    .param p1, "efid"    # I

    .prologue
    const/4 v3, 0x0

    const/16 v2, 0x64

    .line 307
    packed-switch p1, :pswitch_data_0

    .line 338
    :goto_0
    :pswitch_0
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V

    .line 306
    :goto_1
    return-void

    .line 309
    :pswitch_1
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 310
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;

    invoke-direct {v1, p0, v3}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;)V

    .line 309
    invoke-virtual {p0, v2, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f02

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V

    .line 311
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    goto :goto_1

    .line 315
    :pswitch_2
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 316
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;

    invoke-direct {v1, p0, v3}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;)V

    .line 315
    invoke-virtual {p0, v2, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f04

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V

    .line 317
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    goto :goto_1

    .line 321
    :pswitch_3
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 322
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;

    invoke-direct {v1, p0, v3}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;)V

    .line 321
    invoke-virtual {p0, v2, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f03

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V

    .line 323
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    goto :goto_1

    .line 327
    :pswitch_4
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 328
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;

    invoke-direct {v1, p0, v3}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;)V

    .line 327
    invoke-virtual {p0, v2, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f07

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V

    .line 329
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    goto :goto_1

    .line 333
    :pswitch_5
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 334
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;

    invoke-direct {v1, p0, v3}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;)V

    .line 333
    invoke-virtual {p0, v2, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f09

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V

    .line 335
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    goto :goto_0

    .line 307
    nop

    :pswitch_data_0
    .packed-switch 0x6f02
        :pswitch_1
        :pswitch_3
        :pswitch_2
        :pswitch_0
        :pswitch_0
        :pswitch_4
        :pswitch_0
        :pswitch_5
    .end packed-switch
.end method

.method private handleIsimRefresh(Lcom/android/internal/telephony/uicc/IccRefreshResponse;)V
    .locals 2
    .param p1, "refreshResponse"    # Lcom/android/internal/telephony/uicc/IccRefreshResponse;

    .prologue
    .line 344
    if-nez p1, :cond_0

    .line 345
    const-string/jumbo v0, "handleIsimRefresh received without input"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 346
    return-void

    .line 349
    :cond_0
    iget-object v0, p1, Lcom/android/internal/telephony/uicc/IccRefreshResponse;->aid:Ljava/lang/String;

    if-eqz v0, :cond_1

    .line 350
    iget-object v0, p1, Lcom/android/internal/telephony/uicc/IccRefreshResponse;->aid:Ljava/lang/String;

    iget-object v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;

    invoke-virtual {v1}, Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAid()Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_2

    .line 356
    :cond_1
    iget v0, p1, Lcom/android/internal/telephony/uicc/IccRefreshResponse;->refreshResult:I

    packed-switch v0, :pswitch_data_0

    .line 376
    const-string/jumbo v0, "handleIsimRefresh with unknown operation"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 343
    :goto_0
    return-void

    .line 352
    :cond_2
    const-string/jumbo v0, "handleIsimRefresh received different app"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 353
    return-void

    .line 358
    :pswitch_0
    const-string/jumbo v0, "handleIsimRefresh with REFRESH_RESULT_FILE_UPDATE"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 359
    iget v0, p1, Lcom/android/internal/telephony/uicc/IccRefreshResponse;->efId:I

    invoke-direct {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->handleFileUpdate(I)V

    goto :goto_0

    .line 363
    :pswitch_1
    const-string/jumbo v0, "handleIsimRefresh with REFRESH_RESULT_INIT"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 366
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V

    goto :goto_0

    .line 371
    :pswitch_2
    const-string/jumbo v0, "handleIsimRefresh with REFRESH_RESULT_RESET"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    goto :goto_0

    .line 356
    nop

    :pswitch_data_0
    .packed-switch 0x0
        :pswitch_0
        :pswitch_1
        :pswitch_2
    .end packed-switch
.end method

.method private static isimTlvToString([B)Ljava/lang/String;
    .locals 4
    .param p0, "record"    # [B

    .prologue
    .line 273
    new-instance v0, Lcom/android/internal/telephony/gsm/SimTlv;

    array-length v1, p0

    const/4 v2, 0x0

    invoke-direct {v0, p0, v2, v1}, Lcom/android/internal/telephony/gsm/SimTlv;-><init>([BII)V

    .line 275
    .local v0, "tlv":Lcom/android/internal/telephony/gsm/SimTlv;
    :cond_0
    invoke-virtual {v0}, Lcom/android/internal/telephony/gsm/SimTlv;->getTag()I

    move-result v1

    const/16 v2, 0x80

    if-ne v1, v2, :cond_1

    .line 276
    new-instance v1, Ljava/lang/String;

    invoke-virtual {v0}, Lcom/android/internal/telephony/gsm/SimTlv;->getData()[B

    move-result-object v2

    const-string/jumbo v3, "UTF-8"

    invoke-static {v3}, Ljava/nio/charset/Charset;->forName(Ljava/lang/String;)Ljava/nio/charset/Charset;

    move-result-object v3

    invoke-direct {v1, v2, v3}, Ljava/lang/String;-><init>([BLjava/nio/charset/Charset;)V

    return-object v1

    .line 278
    :cond_1
    invoke-virtual {v0}, Lcom/android/internal/telephony/gsm/SimTlv;->nextObject()Z

    move-result v1

    if-nez v1, :cond_0

    .line 280
    const-string/jumbo v1, "IsimUiccRecords"

    const-string/jumbo v2, "[ISIM] can\'t find TLV tag in ISIM record, returning null"

    invoke-static {v1, v2}, Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I

    .line 281
    const/4 v1, 0x0

    return-object v1
.end method

# virtual methods
.method public dispose()V
    .locals 2

    .prologue
    .line 97
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v1, "Disposing "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 99
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mCi:Lcom/android/internal/telephony/CommandsInterface;

    invoke-interface {v0, p0}, Lcom/android/internal/telephony/CommandsInterface;->unregisterForIccRefresh(Landroid/os/Handler;)V

    .line 100
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;

    invoke-virtual {v0, p0}, Lcom/android/internal/telephony/uicc/UiccCardApplication;->unregisterForReady(Landroid/os/Handler;)V

    .line 101
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->resetRecords()V

    .line 102
    invoke-super {p0}, Lcom/android/internal/telephony/uicc/IccRecords;->dispose()V

    .line 96
    return-void
.end method

.method public dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
    .locals 2
    .param p1, "fd"    # Ljava/io/FileDescriptor;
    .param p2, "pw"    # Ljava/io/PrintWriter;
    .param p3, "args"    # [Ljava/lang/String;

    .prologue
    .line 501
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v1, "IsimRecords: "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {p2, v0}, Ljava/io/PrintWriter;->println(Ljava/lang/String;)V

    .line 502
    const-string/jumbo v0, " extends:"

    invoke-virtual {p2, v0}, Ljava/io/PrintWriter;->println(Ljava/lang/String;)V

    .line 503
    invoke-super {p0, p1, p2, p3}, Lcom/android/internal/telephony/uicc/IccRecords;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V

    .line 511
    invoke-virtual {p2}, Ljava/io/PrintWriter;->flush()V

    .line 500
    return-void
.end method

.method protected fetchIsimRecords()V
    .locals 5

    .prologue
    const/4 v4, 0x0

    const/16 v3, 0x64

    .line 163
    const/4 v0, 0x1

    iput-boolean v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsRequested:Z

    .line 165
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 166
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;

    invoke-direct {v1, p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpiLoaded;)V

    .line 165
    invoke-virtual {p0, v3, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f02

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V

    .line 167
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 169
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 170
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;

    invoke-direct {v1, p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimImpuLoaded;)V

    .line 169
    invoke-virtual {p0, v3, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f04

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V

    .line 171
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 173
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 174
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;

    invoke-direct {v1, p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimDomainLoaded;)V

    .line 173
    invoke-virtual {p0, v3, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f03

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V

    .line 175
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 176
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 177
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;

    invoke-direct {v1, p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimIstLoaded;)V

    .line 176
    invoke-virtual {p0, v3, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f07

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V

    .line 178
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 179
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;

    .line 180
    new-instance v1, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;

    invoke-direct {v1, p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;-><init>(Lcom/android/internal/telephony/uicc/IsimUiccRecords;Lcom/android/internal/telephony/uicc/IsimUiccRecords$EfIsimPcscfLoaded;)V

    .line 179
    invoke-virtual {p0, v3, v1}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(ILjava/lang/Object;)Landroid/os/Message;

    move-result-object v1

    const/16 v2, 0x6f09

    invoke-virtual {v0, v2, v1}, Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V

    .line 181
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, 0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 183
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v1, "fetchIsimRecords "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    iget v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v0

    const-string/jumbo v1, " requested: "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    iget-boolean v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsRequested:Z

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 162
    return-void
.end method

.method public getDisplayRule(Ljava/lang/String;)I
    .locals 1
    .param p1, "plmn"    # Ljava/lang/String;

    .prologue
    .line 460
    const/4 v0, 0x0

    return v0
.end method

.method public getIsimChallengeResponse(Ljava/lang/String;)Ljava/lang/String;
    .locals 5
    .param p1, "nonce"    # Ljava/lang/String;

    .prologue
    .line 437
    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v3, "getIsimChallengeResponse-nonce:"

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-virtual {p0, v2}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 439
    :try_start_0
    iget-object v3, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;

    monitor-enter v3
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_1

    .line 440
    :try_start_1
    iget-object v2, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mCi:Lcom/android/internal/telephony/CommandsInterface;

    const/16 v4, 0x5a

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->obtainMessage(I)Landroid/os/Message;

    move-result-object v4

    invoke-interface {v2, p1, v4}, Lcom/android/internal/telephony/CommandsInterface;->requestIsimAuthentication(Ljava/lang/String;Landroid/os/Message;)V
    :try_end_1
    .catchall {:try_start_1 .. :try_end_1} :catchall_0

    .line 442
    :try_start_2
    iget-object v2, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;

    invoke-virtual {v2}, Ljava/lang/Object;->wait()V
    :try_end_2
    .catch Ljava/lang/InterruptedException; {:try_start_2 .. :try_end_2} :catch_0
    .catchall {:try_start_2 .. :try_end_2} :catchall_0

    :goto_0
    :try_start_3
    monitor-exit v3
    :try_end_3
    .catch Ljava/lang/Exception; {:try_start_3 .. :try_end_3} :catch_1

    .line 452
    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v3, "getIsimChallengeResponse-auth_rsp"

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    iget-object v3, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-virtual {p0, v2}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 454
    iget-object v2, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;

    return-object v2

    .line 443
    :catch_0
    move-exception v1

    .line 444
    .local v1, "e":Ljava/lang/InterruptedException;
    :try_start_4
    const-string/jumbo v2, "interrupted while trying to request Isim Auth"

    invoke-virtual {p0, v2}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V
    :try_end_4
    .catchall {:try_start_4 .. :try_end_4} :catchall_0

    goto :goto_0

    .line 439
    .end local v1    # "e":Ljava/lang/InterruptedException;
    :catchall_0
    move-exception v2

    :try_start_5
    monitor-exit v3

    throw v2
    :try_end_5
    .catch Ljava/lang/Exception; {:try_start_5 .. :try_end_5} :catch_1

    .line 447
    :catch_1
    move-exception v0

    .line 448
    .local v0, "e":Ljava/lang/Exception;
    const-string/jumbo v2, "Fail while trying to request Isim Auth"

    invoke-virtual {p0, v2}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 449
    const/4 v2, 0x0

    return-object v2
.end method

.method public getIsimDomain()Ljava/lang/String;
    .locals 1

    .prologue
    .line 398
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimDomain:Ljava/lang/String;

    return-object v0
.end method

.method public getIsimImpi()Ljava/lang/String;
    .locals 1

    .prologue
    .line 388
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpi:Ljava/lang/String;

    return-object v0
.end method

.method public getIsimImpu()[Ljava/lang/String;
    .locals 2

    .prologue
    const/4 v0, 0x0

    .line 408
    iget-object v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;

    if-eqz v1, :cond_0

    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;

    invoke-virtual {v0}, Ljava/lang/Object;->clone()Ljava/lang/Object;

    move-result-object v0

    check-cast v0, [Ljava/lang/String;

    :cond_0
    return-object v0
.end method

.method public getIsimIst()Ljava/lang/String;
    .locals 1

    .prologue
    .line 417
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimIst:Ljava/lang/String;

    return-object v0
.end method

.method public getIsimPcscf()[Ljava/lang/String;
    .locals 2

    .prologue
    const/4 v0, 0x0

    .line 427
    iget-object v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;

    if-eqz v1, :cond_0

    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;

    invoke-virtual {v0}, Ljava/lang/Object;->clone()Ljava/lang/Object;

    move-result-object v0

    check-cast v0, [Ljava/lang/String;

    :cond_0
    return-object v0
.end method

.method public getVoiceMessageCount()I
    .locals 1

    .prologue
    .line 516
    const/4 v0, 0x0

    return v0
.end method

.method public handleMessage(Landroid/os/Message;)V
    .locals 7
    .param p1, "msg"    # Landroid/os/Message;

    .prologue
    .line 109
    iget-object v4, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mDestroyed:Ljava/util/concurrent/atomic/AtomicBoolean;

    invoke-virtual {v4}, Ljava/util/concurrent/atomic/AtomicBoolean;->get()Z

    move-result v4

    if-eqz v4, :cond_0

    .line 110
    const-string/jumbo v4, "IsimUiccRecords"

    new-instance v5, Ljava/lang/StringBuilder;

    invoke-direct {v5}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v6, "Received message "

    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v5

    invoke-virtual {v5, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v5

    .line 111
    const-string/jumbo v6, "["

    .line 110
    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v5

    .line 111
    iget v6, p1, Landroid/os/Message;->what:I

    .line 110
    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v5

    .line 111
    const-string/jumbo v6, "] while being destroyed. Ignoring."

    .line 110
    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v5

    invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v5

    invoke-static {v4, v5}, Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I

    .line 112
    return-void

    .line 114
    :cond_0
    new-instance v4, Ljava/lang/StringBuilder;

    invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v5, "IsimUiccRecords: handleMessage "

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v4

    const-string/jumbo v5, "["

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    iget v5, p1, Landroid/os/Message;->what:I

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v4

    const-string/jumbo v5, "] "

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v4

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->loge(Ljava/lang/String;)V

    .line 117
    :try_start_0
    iget v4, p1, Landroid/os/Message;->what:I

    sparse-switch v4, :sswitch_data_0

    .line 153
    invoke-super {p0, p1}, Lcom/android/internal/telephony/uicc/IccRecords;->handleMessage(Landroid/os/Message;)V

    .line 106
    :cond_1
    :goto_0
    return-void

    .line 119
    :sswitch_0
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->onReady()V
    :try_end_0
    .catch Ljava/lang/RuntimeException; {:try_start_0 .. :try_end_0} :catch_0

    goto :goto_0

    .line 156
    :catch_0
    move-exception v2

    .line 158
    .local v2, "exc":Ljava/lang/RuntimeException;
    const-string/jumbo v4, "IsimUiccRecords"

    const-string/jumbo v5, "Exception parsing SIM record"

    invoke-static {v4, v5, v2}, Landroid/telephony/Rlog;->w(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I

    goto :goto_0

    .line 123
    .end local v2    # "exc":Ljava/lang/RuntimeException;
    :sswitch_1
    :try_start_1
    iget-object v0, p1, Landroid/os/Message;->obj:Ljava/lang/Object;

    check-cast v0, Landroid/os/AsyncResult;

    .line 124
    .local v0, "ar":Landroid/os/AsyncResult;
    new-instance v4, Ljava/lang/StringBuilder;

    invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v5, "ISim REFRESH(EVENT_ISIM_REFRESH) with exception: "

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    iget-object v5, v0, Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v4

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->loge(Ljava/lang/String;)V

    .line 125
    iget-object v4, v0, Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;

    if-nez v4, :cond_1

    .line 126
    new-instance v3, Landroid/content/Intent;

    const-string/jumbo v4, "com.android.intent.isim_refresh"

    invoke-direct {v3, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V

    .line 127
    .local v3, "intent":Landroid/content/Intent;
    const-string/jumbo v4, "send ISim REFRESH: com.android.intent.isim_refresh"

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->loge(Ljava/lang/String;)V

    .line 128
    iget-object v4, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mContext:Landroid/content/Context;

    invoke-virtual {v4, v3}, Landroid/content/Context;->sendBroadcast(Landroid/content/Intent;)V

    .line 129
    iget-object v4, v0, Landroid/os/AsyncResult;->result:Ljava/lang/Object;

    check-cast v4, Lcom/android/internal/telephony/uicc/IccRefreshResponse;

    invoke-direct {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->handleIsimRefresh(Lcom/android/internal/telephony/uicc/IccRefreshResponse;)V

    goto :goto_0

    .line 134
    .end local v0    # "ar":Landroid/os/AsyncResult;
    .end local v3    # "intent":Landroid/content/Intent;
    :sswitch_2
    iget-object v0, p1, Landroid/os/Message;->obj:Ljava/lang/Object;

    check-cast v0, Landroid/os/AsyncResult;

    .line 135
    .restart local v0    # "ar":Landroid/os/AsyncResult;
    const-string/jumbo v4, "EVENT_AKA_AUTHENTICATE_DONE"

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 136
    iget-object v4, v0, Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;

    if-eqz v4, :cond_2

    .line 137
    new-instance v4, Ljava/lang/StringBuilder;

    invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v5, "Exception ISIM AKA: "

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    iget-object v5, v0, Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v4

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 146
    :goto_1
    iget-object v5, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;

    monitor-enter v5
    :try_end_1
    .catch Ljava/lang/RuntimeException; {:try_start_1 .. :try_end_1} :catch_0

    .line 147
    :try_start_2
    iget-object v4, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;

    invoke-virtual {v4}, Ljava/lang/Object;->notifyAll()V
    :try_end_2
    .catchall {:try_start_2 .. :try_end_2} :catchall_0

    :try_start_3
    monitor-exit v5
    :try_end_3
    .catch Ljava/lang/RuntimeException; {:try_start_3 .. :try_end_3} :catch_0

    goto :goto_0

    .line 140
    :cond_2
    :try_start_4
    iget-object v4, v0, Landroid/os/AsyncResult;->result:Ljava/lang/Object;

    check-cast v4, Ljava/lang/String;

    iput-object v4, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;

    .line 141
    new-instance v4, Ljava/lang/StringBuilder;

    invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v5, "ISIM AKA: auth_rsp = "

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    iget-object v5, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v4

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V
    :try_end_4
    .catch Ljava/lang/Exception; {:try_start_4 .. :try_end_4} :catch_1
    .catch Ljava/lang/RuntimeException; {:try_start_4 .. :try_end_4} :catch_0

    goto :goto_1

    .line 142
    :catch_1
    move-exception v1

    .line 143
    .local v1, "e":Ljava/lang/Exception;
    :try_start_5
    new-instance v4, Ljava/lang/StringBuilder;

    invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v5, "Failed to parse ISIM AKA contents: "

    invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

    move-result-object v4

    invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v4

    invoke-virtual {p0, v4}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    goto :goto_1

    .line 146
    .end local v1    # "e":Ljava/lang/Exception;
    :catchall_0
    move-exception v4

    monitor-exit v5

    throw v4
    :try_end_5
    .catch Ljava/lang/RuntimeException; {:try_start_5 .. :try_end_5} :catch_0

    .line 117
    nop

    :sswitch_data_0
    .sparse-switch
        0x1 -> :sswitch_0
        0x1f -> :sswitch_1
        0x5a -> :sswitch_2
    .end sparse-switch
.end method

.method protected log(Ljava/lang/String;)V
    .locals 3
    .param p1, "s"    # Ljava/lang/String;

    .prologue
    .line 491
    const-string/jumbo v0, "IsimUiccRecords"

    new-instance v1, Ljava/lang/StringBuilder;

    invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v2, "[ISIM] "

    invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/telephony/Rlog;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 490
    return-void
.end method

.method protected loge(Ljava/lang/String;)V
    .locals 3
    .param p1, "s"    # Ljava/lang/String;

    .prologue
    .line 496
    const-string/jumbo v0, "IsimUiccRecords"

    new-instance v1, Ljava/lang/StringBuilder;

    invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v2, "[ISIM] "

    invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I

    .line 495
    return-void
.end method

.method protected onAllRecordsLoaded()V
    .locals 3

    .prologue
    const/4 v2, 0x0

    .line 301
    const-string/jumbo v0, "record load complete"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 302
    iget-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsLoadedRegistrants:Landroid/os/RegistrantList;

    .line 303
    new-instance v1, Landroid/os/AsyncResult;

    invoke-direct {v1, v2, v2, v2}, Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V

    .line 302
    invoke-virtual {v0, v1}, Landroid/os/RegistrantList;->notifyRegistrants(Landroid/os/AsyncResult;)V

    .line 300
    return-void
.end method

.method public onReady()V
    .locals 0

    .prologue
    .line 465
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V

    .line 464
    return-void
.end method

.method protected onRecordLoaded()V
    .locals 3

    .prologue
    const/4 v2, 0x0

    .line 288
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    add-int/lit8 v0, v0, -0x1

    iput v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    .line 289
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v1, "onRecordLoaded "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    iget v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v0

    const-string/jumbo v1, " requested: "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    iget-boolean v1, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsRequested:Z

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V

    .line 291
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    if-nez v0, :cond_1

    iget-boolean v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsRequested:Z

    if-eqz v0, :cond_1

    .line 292
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->onAllRecordsLoaded()V

    .line 285
    :cond_0
    :goto_0
    return-void

    .line 293
    :cond_1
    iget v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    if-gez v0, :cond_0

    .line 294
    const-string/jumbo v0, "recordsToLoad <0, programmer error suspected"

    invoke-virtual {p0, v0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->loge(Ljava/lang/String;)V

    .line 295
    iput v2, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsToLoad:I

    goto :goto_0
.end method

.method public onRefresh(Z[I)V
    .locals 0
    .param p1, "fileChanged"    # Z
    .param p2, "fileList"    # [I

    .prologue
    .line 470
    if-eqz p1, :cond_0

    .line 474
    invoke-virtual {p0}, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V

    .line 469
    :cond_0
    return-void
.end method

.method protected resetRecords()V
    .locals 1

    .prologue
    const/4 v0, 0x0

    .line 190
    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpi:Ljava/lang/String;

    .line 191
    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimDomain:Ljava/lang/String;

    .line 192
    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;

    .line 193
    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimIst:Ljava/lang/String;

    .line 194
    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;

    .line 195
    iput-object v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;

    .line 197
    const/4 v0, 0x0

    iput-boolean v0, p0, Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mRecordsRequested:Z

    .line 186
    return-void
.end method

.method public setVoiceMailNumber(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
    .locals 0
    .param p1, "alphaTag"    # Ljava/lang/String;
    .param p2, "voiceNumber"    # Ljava/lang/String;
    .param p3, "onComplete"    # Landroid/os/Message;

    .prologue
    .line 480
    return-void
.end method

.method public setVoiceMessageWaiting(II)V
    .locals 0
    .param p1, "line"    # I
    .param p2, "countWaiting"    # I

    .prologue
    .line 485
    return-void
.end method

.method public toString()Ljava/lang/String;
    .locals 2

    .prologue
    .line 72
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    const-string/jumbo v1, "IsimUiccRecords: "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-super {p0}, Lcom/android/internal/telephony/uicc/IccRecords;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    .line 77
    const-string/jumbo v1, ""

    .line 72
    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    return-object v0
.end method


text:
title: "A Primer on Reinforcement Learning: Q-Learning"
layout: post
date: 2018-11-1 10:43
image: '/assets/images/'
description:
tag:
blog: true
jemoji:
author:
---

Reinforcement Learning is a field of Machine Learning which aims to develop intelligences that learn through trial and error by exploring and interacting with their environment.

You may have seen exciting demos of an AI learning to play video games or robot arms learning to manipulate objects or mimic tasks.

In this post, we'll look at a very basic approach to Reinforcement Learning which we can use to learn to play very simple games. It's a limited approach and we'll quickly find problems with it, but that will set us up nicely for a follow up post on how we can improve on this technique

## State, Actions and Rewards

Reinforcement Learning (RL) consists of two actors: an agent (our model / algorithm), and the environment (the game we're playing in this case). Our agent seeks to develop an optimal policy for interacting with the environment that maximises the cumulative reward over time.

Our environment is represented by a series of *states*. If we think of a grid with a single playing piece, we can transition states by moving our piece around the board. Each move takes us to a different possible state that the game can be in. We have several different things we can do to our piece, known as *actions*. We can move up, down, left, or right. Each of these actions transitions us to a new state and brings us one step closer to, or further away from, our goal state (usually a state that will win the game).

When we take an action in our game, we receive some feedback, usually in the form of a score. It's this *reward* that we seek to maximise over our time playing the game.

In short, our agent interacts with our environment by choosing *actions* (a) to take at a particular *state* (s) with the intention of maximising future *rewards* (r) received. It's this mapping of what action we should take at what particular state that's the problem that we need to solve and is referred to as the *policy* (π), with the optimal policy being denoted as *π**

![The Reinforcement Learning Cycle](/assets/images/a_primer_on_reinforcement_learning/cycle.png)

## The Q-Table

There are a lot of different techniques that we can use to get our model to converge on an optimal policy but in this post, we're going to go for the one which allows us to get something up and running quickly.

Q-Learning is a technique that seeks to assess the *quality* of taking a given action at a given state. If we drew up a table, with all our game states as rows, and all our possible actions as columns. We could use it as a cheat sheet to keep track of the rewards we recieve for a state action pair over time. If we move left at state 1, and receive a reward of +1, we'll write that down in our table. Over time, we'll begin to build up a picture of the quality of every action we can take at every state, and could easily select the actions with the biggest score, or Q-value, to cheat our way to the end of the game.

But this raises two important questions, how do we update our score for each state action pair? And, how do we move around our game when we have no values in our table yet?

## The Bellman Equation

The Bellman Equation provides the foundation for assessing the quality of taking a given action at a given state. If we know the rewards at each state in the game, for example, landing on a safe tile is +1 point, and losing the game is -10 points, we can use the Bellman equation to calculate the optimal Q-value for each state action pair.

We'll iteratively update our Q-values in our Q-table until we converge to the optimal policy, seeking to reduce the loss between our Q-value, and our optimal Q-value.

Firstly, we'll need to take an action from our state. Then we'll receive our reward, along with a new state. We can use this new information, along with the information of the action we took at the previous state to assess how good or bad our move was.

What if we come across a reward for a state action pair we've already seen? Over writing previous Q-values would lose valuable information about previous game plays. Instead, we can use a learning rate to update our Q-value. The higher the learning rate, the more quickly our agent will adopt new values and disregard previous values. With a learning rate of 1.0, our agent would simply rewrite all the old values with new values each time.

![The Bellman Equation](/assets/images/a_primer_on_reinforcement_learning/bellman.png)

## Exploration vs Exploitation

Imagine our agent is playing a game with an empty Q table. Initially, it'll be fairly useless, so using it as a policy to follow won't get us anywhere. In fact, when we do build up values in our Q table, we'll want to avoid using them too early before they've converged. If we exploit our table too soon, we'll get stuck at early rewards and possibly miss out on taking larger rewards that could benefit us long term.

Instead, we'll want to strike a decaying balance between how much we want to explore the games state spaces to find new rewards, and how much we want to exploit our Q table for the correct answers. This is referred to as exploration vs exploitation.

We'll do this with a strategy known as *epsilon greedy*. We'll set an `epsilon` number, which represents our probability of choosing exploration vs exploitation. With epsilon set to 1.0, we have a 100% chance that we'll explore our environment, and thus take actions entirely at random. With epsilon at 0, we'll exploit our Q-table and select the action with the highest value. As we iterate through our training, we'll slowly decay epsilon by `gamma`, a small number, that will make it less and less probable over time that we'll explore our environment by selecting random actions.

## Frozen Lake

Frozen Lake is a game where we have to navigate a 4x4 grid of tiles, each of a different surface type. S is our starting point, G is our goal point, F are frozen tiles (safe to step on) and H are holes which we can fall into and lose the game. We'll train an agent to safely navigate from the starting tile to our goal tile using Q-Learning.

```python
SFFF
FHFH
FFFH
HFFG
```

We'll first import OpenAI's gym library, which will give us the FrozenLake game, with a nice wrapper to be able to access actions and the state space. We'll also require numpy and random.

```python
import numpy as np
import random
import gym
```

Next we'll start up our FrozenLake game and assign the environment to a variable we can use later on

```python
env = gym.make("FrozenLake-v0")
```

In order to form our Q table, we'll need to know the number of possible actions and states. We'll then create an empty table, initialised with zeros at the moment, that we can later update throughout our training with our Q values, much like how we update weights in a neural network. Our Q table acts like a cheat sheet, reflecting the quality of taking that particular action, at a particular state.

```python
action_size = env.action_space.n
state_size = env.observation_space.n

qtable = np.zeros((state_size, action_size))
print(qtable)
```

```python
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
```

Let's set some hyperparameters...

```python
episodes       = 10000      # Total episodes
max_steps      = 99         # Max moves per episode - stops us exploring infinitely

learning_rate  = 0.8        # Learning rate
gamma          = 0.95       # Discounting rate

epsilon        = 1.0        # Exploration vs exploitation rate
decay_rate     = 0.001      # How much we want to decay our exploration vs exploitation rate
```

We'll write some helper functions that will make it easier to understand what our code is doing without getting caught up in the formulas.

Firstly, we'll need a function that, over time, will make a gradual progression from exploration of our environment, to exploitation by utilising our Q table. We'll use epsilon to denote our exploration vs exploitation rate, and reduce it by our `decay_rate` for every episode.

`max_epsilon` is the largest our epsilon can be and represents a full 100% chance we'll explore our environment. Conversely, `min_epsilon` represents a 100% chance that we'll exploit our Q table for the correct answers.

```python
def reduce_epsilon(episode, min_epsilon=0.01, max_epsilon=1.0, decay_rate=0.001):
    return min_epsilon + (max_epsilon - min_epsilon) * np.exp(-decay_rate * episode)
```

Epsilon will be used in selecting wether we want to explore our environment, which we'll do by selecting an action at random, or wether we want to exploit our learned Q-table, which we can do by selecting the action with the highest Q value.

Since this is fairly simply logic, we can code this into another helper function which will help simplify our code...

Here we take in some information like our `epsilon`, our `qtable`, `state` and the `env` (environment) and generate a random number. If our number is larger than epsilon, we'll choose to exploit our Q-table by selecting the action with the highest Q-value. If our number is lower than epsilon, we'll explore our environment further by selecting a random action from our action space.

```python
def select_action(epsilon, qtable, state, env):
    x = random.uniform(0,1)

    if x > epsilon:
        # Exploitation
        return np.argmax(qtable[state,:])
    else:
        # Exploration
        return env.action_space.sample()
```

Lastly, we'll need a function to update the values in our Q-table based upon the Bellman equation given our previous state, action taken, reward, and new state...

```python
def update_qtable(qtable, state, action, reward, new_state, learning_rate, gamma):
    # Update Q(s,a):= Q(s,a) + lr [R(s,a) + gamma * max Q(s',a') - Q(s,a)]
    # qtable[new_state,:] : all the actions we can take from new state

    qtable[state, action] = qtable[state, action] + learning_rate * (reward + gamma * np.max(qtable[new_state, :]) - qtable[state, action])
    return qtable
```

## Training our Q-Table

Next up is the bulk of our code. This is where we'll put the pieces together, train our agent, and populate our Q-table.

For every episode in our total number of `episodes`, we'll firstly reset our environment and a few variables which will keep track of game play for that particular run. For each step, we'll use our `select_action()` function to choose an action, either at random (exploration) or from our Q-table (exploitation). This rate will gradually ramp towards more and more exploitation over time as we build up our Q-table.

We'll then take our action and observe the reward and new state returned, which we'll use to update our Q-table. Finally, we'll we'll set our `state` to be the `new_state` that we received by taking an action, reduce `epsilon` to lean slightly more towards exploitation, add our reward to a list so that we can keep track of how we're improving over time, and start the cycle over again until we reach some terminal state in our game (we fall into a hole, or win the game).

```python
rewards = []

for episode in range(episodes):
    # Reset the environment
    state = env.reset()
    step = 0
    done = False
    total_rewards = 0

    for step in range(max_steps):
        # Use epsilon to pick an action, either at random, or from our q-table
        action = select_action(epsilon, qtable, state, env)

        # Take the action and observe the new state and reward
        new_state, reward, done, info = env.step(action)

        # Update our Q-table to take note of how valuable the action according to the reward we got
        qtable = update_qtable(qtable, state, action, reward, new_state, learning_rate, gamma)

        # Set state to the new state we received (where we moved to)
        state = new_state

        total_rewards += reward

        # If the game is over, exit the loop, back to a new training loop
        if done == True:
            break

        epsilon = reduce_epsilon(episode)

    rewards.append(total_rewards)

print("Score over time: " +  str(sum(rewards)/total_episodes))
print(qtable)
```

## Playing the Game

Once we've populated our Q-table, we can exploit it to play the game successfully. As we're simply following our Q-table, we no longer have to deal with updating our table, or dealing with our exploration vs exploitation trade off. We can simply just follow the policy of selecting the highest value at a given state. With a well trained Q-table, our values should closely reflect the maximum expected reward over time by taking that particular action at that particular state.

```python
env.reset()

for episode in range(5):
    state = env.reset()
    step = 0
    done = False
    print("Playing Round #", episode)

    for step in range(max_steps):
        # Select the action with the highest reward
        action = np.argmax(qtable[state,:])

        # Return our new state and reward
        new_state, reward, done, info = env.step(action)

        if done:
            # If the game is finished, we'll print our environment to see if we fell into a hole, or ended on our goal tile
            env.render()

            # We print the number of steps it took.
            print("Steps taken:", step)
            break

        state = new_state

env.close()
```

## Summary

And there we have it! We successfully trained a model to learn play the Frozen Lake game by exploring the environment itself, and learning through trial and error.

But what happens when we want to play a more complex game with millions of possible states? Unfortunately, as your state space grows, you very quickly out grow the feasibility of using a Q-table. It would take millions of iterations to even begin to explore all the possible state spaces and build up an accurate Q-table.

Instead of creating a cheat sheet that we can look up every possible value for every possible action in every possible state, what if we could just simplify by having a function that approximates the Q-value for a given state action pair?

If you have read previous posts, you may be familiar with one tool that we can use for function approximation; the neural network.

In a future post we'll look at how we can improve on our reinforcement learning agent by using neural networks to apply our techniques to larger state spaces and more complex games with Deep Q-Learning.


text:
/*global Promise */

sap.ui.define([
	"sap/ui/fl/LrepConnector", "sap/ui/fl/Utils"
], function(LrepConnector, FlexUtils) {
	"use strict";

	/**
	 * Entity that handles ABAP transport related information.
	 * @constructor
	 * @alias sap.ui.fl.transport.Transports
	 * @author SAP SE
	 * @version ${version}
	 * @since 1.38.0
	 */
	var Transports = function() {
	};

	/**
	 * Reads the transports of the current user from the back end.
	 * The "locked" attribute indicates that the provided file (package/name/type) is already locked on this transport.
	 *
	 * @param {object} mParameters map of parameters, see below
	 * @param {string} mParameters.package - abap package; only relevant for VENDOR layer
	 * @param {string} mParameters.name - name of the lrep document
	 * @param {string} mParameters.namespace - namespace of the lrep document
	 * @param {string} mParameters.type - file extension of the lrep document
	 * @returns {Promise} with parameter oResult
	 * 					which is an object that has the attributes "transports", "localonly" and "errorCode".
	 * 					"localonly" tells the consumer if only local development is valid and no transport selection should take place.
	 * 					"transports" is an array of objects with attributes "transportId", "owner", "description", "locked"(true/false).
	 * 					"errorCode" can have the values "INVALID_PACKAGE" or "NO_TRANSPORTS" or is an empty string if there is no error.
	 * @public
	 */
	Transports.prototype.getTransports = function(mParameters) {
		var sUri, sClient, oLrepConnector, oPromise;
		sUri = '/sap/bc/lrep/actions/gettransports/';
		if (mParameters['package']) {
			sUri += '&package=' + mParameters['package'];
		}
		if (mParameters.name) {
			sUri += '&name=' + mParameters.name;
		}
		if (mParameters.namespace) {
			sUri += '&namespace=' + mParameters.namespace;
		}
		if (mParameters.type) {
			sUri += '&type=' + mParameters.type;
		}
		sClient = FlexUtils.getClient();
		if (sClient) {
			sUri += '&sap-client=' + sClient;
		}
		//Replace first & with ?
		sUri = sUri.replace('&', '?');

		oLrepConnector = LrepConnector.createConnector();
		oPromise = oLrepConnector.send(sUri);
		return oPromise.then(function(oResponse) {
			if (oResponse.response) {
				if (!oResponse.response.localonly) {
					oResponse.response.localonly = false;
				}
				if (!oResponse.response.errorCode) {
					oResponse.response.errorCode = "";
				}
				return Promise.resolve(oResponse.response);
			} else {
				return Promise.reject('response is empty');
			}
		});
	};

	/**
	 * Reads the transports of the current user from the back end.
	 * The "locked" attribute indicates that the provided file (package/name/type) is already locked on this transport.
	 *
	 * @param {object} mParameters map of parameters, see below
	 * @param {string} mParameters.transportId - ABAP transport ID
	 * @param {string} mParameters.changeIds - array of change ID objects with attributes "namespace", "fileName", "fileType"
	 * @returns {Promise} without parameters
	 * @public
	 */
	Transports.prototype.makeChangesTransportable = function(mParameters) {
		var sUri, sClient, oLrepConnector;
		sUri = '/sap/bc/lrep/actions/make_changes_transportable/';
		sClient = FlexUtils.getClient();
		if (sClient) {
			sUri += '?sap-client=' + sClient;
		}
		if (!mParameters.transportId) {
			return Promise.reject(new Error("no transportId provided as attribute of mParameters"));
		}
		if (!mParameters.changeIds) {
			return Promise.reject(new Error("no changeIds provided as attribute of mParameters"));
		}
		oLrepConnector = LrepConnector.createConnector();
		return oLrepConnector.send(sUri,'POST',mParameters);
	};

	/**
	 * Get list of changes which should be added to a transport
	 *
	 * @param {Array} aLocalChanges List of changes which data have to be extracted
	 * @returns {Array} Returns an array of object containing all required data to transport the existing local changes
	 */
	Transports.prototype._convertToChangeTransportData = function(aLocalChanges) {
		var aTransportData = [];
		var len = aLocalChanges.length;
		for (var i = 0; i < len; i++) {
			var oCurrentChange = aLocalChanges[i];
			var oData = {};
			oData.namespace = oCurrentChange.getNamespace();
			oData.fileName = oCurrentChange.getId();
			oData.fileType = oCurrentChange.getDefinition().fileType;
			aTransportData.push(oData);
		}
		return aTransportData;
	};

	return Transports;
}, /* bExport= */true);


text:
set -e

DIR=/docker-entrypoint.d

# Execute entrypoint hooks (runtime configurations)
if [ -d "$DIR" ]; then
  echo "===> Executing entrypoint hooks under docker-entrypoint.d"
  /bin/run-parts --verbose --regex '\.(sh|rb)$' "$DIR"
  echo "===> End of hooks"
fi

# Run CMD
exec "$@"


text:
project_path: /web/_project.yaml
book_path: /web/updates/_book.yaml
description: An round up of the deprecations and API removals in Chrome to help you plan.

{# wf_updated_on: 2016-07-28 #}
{# wf_published_on: 2016-02-01 #}
{# wf_tags: deprecations,removals,chrome49 #}
{# wf_featured_image: /web/updates/images/generic/warning.png #}

# API Deprecations and Removals in Chrome 49  {: .page-title }

{% include "web/_shared/contributors/paulkinlan.html" %}

In nearly every version of Chrome we see a significant number of updates and
improvements to the product, its performance, and also capabilities of the web
platform.

<<../../_deprecation-policy.md>>

In Chrome 49 (Beta Feb 2nd, 2016. Estimated stable date: March 2016) there are a
number of changes to Chrome

## Use of "css" prefix in getComputedStyle(e).cssX is deprecated

**TL;DR**: The use of the "css" prefix in
[`getComputedStyle(e)`](https://code.google.com/p/chromium/issues/detail?id=413205)
has been deprecated since it was not a part of the formal
[spec](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle).

* [Intent to Remove](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/SX901460nbI)
* [Chromestatus Tracker](https://www.chromestatus.com/features/5006796888473600)
* [CRBug Issue](https://code.google.com/p/chromium/issues/detail?id=413205)

`getComputedStyle` is a great little function.  It will return all CSS values of
the DOM element's styles as they have been computed by the rendering engine.  So
for example, you could run `getComputedStyle(_someElement_).height` and it might
return 224.1px because that is the height of the element as it is currently
displayed.

It seems quite a handy API. So what are we changing?

Before the rendering engine of Chrome changed to Blink, it was powered by
WebKit and that had let you prefix "css" to the start of a property.  For
example `getComputedStyle(e).cssHeight` instead of `getComputedStyle(e).height`.
Both would return the same data as they mapped to the same underlying values,
but it is this usage of the "css" prefix that is non-standard and has been
deprecated and removed.

Note - `cssFloat` is a standard property and is not affected by this deprecation.

If you access a property this way in Chrome 49 it will return `undefined` and you
will have to fix your code.

## Use of initTouchEvent is deprecated.

**TL;DR**:
[`initTouchEvent`](https://w3c.github.io/touch-events/#dictionary-toucheventinit-members)
has been deprecated in favor of the
[`TouchEvent`](https://w3c.github.io/touch-events/#touch-interface)
[`constructor`](https://w3c.github.io/touch-events/#touch-interface) to improve
spec compliance and will be removed altogether in Chrome 54.

[Intent to Remove](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/dqlJguVuIHs)
[Chromestatus Tracker](https://www.chromestatus.com/features/5730982598541312)
[CRBug Issue](https://code.google.com/p/chromium/issues/detail?id=522100)

For a long time you have been able to create synthetic touch events in Chrome
using the `initTouchEvent` API, these are frequently used to simulate Touch Events
either for testing or automating some UI in your site.  In Chrome 49 we have
deprecated this API and will display the following warning with the intention
to remove it completely in Chrome 53.

    'TouchEvent.initTouchEvent' is deprecated and will be removed in M53,
    around September 2016. Please use the TouchEvent constructor instead. See

    https://www.chromestatus.com/features/5730982598541312 for more details.

There are a number of reasons why [this change is good](https://miketaylr.com/posts/2015/09/init-touch-event-is-a-rats-nest.html).
It is also not in the Touch Events spec. The Chrome implementation of
`initTouchEvent` was not compatible at all with Safari's `initTouchEvent` API and
was different to Firefox on Android's. And finally, the `TouchEvent` constructor
is a lot easier to use.

It was decided that we will aim to follow the spec rather than maintain an API
that is neither specced nor compatible with the only other implementation.
Consequently we are first deprecating and then removing the `initTouchEvent`
function and requiring developers to use the `TouchEvent` constructor.

There **is** usage of this API on the Web but we know it is used by a relatively
low number of sites so we are not removing it as quickly as we might normally.
We do believe that some of the usage is broken due to sites not handling
Chrome's version of the signature.

Because the iOS and Android/Chrome implementations of the `initTouchEvent` API
were so wildly different you would often have some [code along the lines
of](https://gist.github.com/basecss/8666646) (frequently forgetting Firefox)

    var event = document.createEvent('TouchEvent');

    if(ua === 'Android') {
      event.initTouchEvent(touchItem, touchItem, touchItem, "touchstart", window,
        300, 300, 200, 200, false, false, false, false);
    } else {
      event.initTouchEvent("touchstart", false, false, window, 0, 300, 300, 200,
        200, false, false, false, false, touches, targetTouches, changedTouches, 0, 0);
    }

    document.body.dispatchEvent(touchEvent);

Firstly, this is bad because it looks for "Android" in the User-Agent and Chrome
on Android will match and hit this deprecation.  It can't be removed just yet
though because there will be other WebKit and older Blink based browsers on
Android for a while that you will still need to support the older API.

To correctly handle `TouchEvents` on the web you should change your code to
support Firefox, IE Edge, and Chrome by checking for the existence of `TouchEvent`
on the `window` object and if it has a positive "length" (indicating it's a
constructor that takes an argument) you should use that.

    if('TouchEvent' in window && TouchEvent.length > 0) {
      var touch = new Touch({
        identifier: 42,
        target: document.body,
        clientX: 200,
        clientY: 200,
        screenX: 300,
        screenY: 300,
        pageX: 200,
        pageY: 200,
        radiusX: 5,
        radiusY: 5
      });

      event = new TouchEvent("touchstart", {
        cancelable: true,
        bubbles: true,
        touches: [touch],
        targetTouches: [touch],
        changedTouches: [touch]
      });
    }
    else {
      event = document.createEvent('TouchEvent');

      if(ua === 'Android') {
        event.initTouchEvent(touchItem, touchItem, touchItem, "touchstart", window,
          300, 300, 200, 200, false, false, false, false);
      } else {
        event.initTouchEvent("touchstart", false, false, window, 0, 300, 300, 200,
          200, false, false, false, false, touches, targetTouches,
          changedTouches, 0, 0);
      }
    }

    document.body.dispatchEvent(touchEvent);

## Error and success handlers required in RTCPeerConnection methods

**TL;DR:** The [WebRTC](http://www.html5rocks.com/en/tutorials/webrtc/basics/){: .external }
RTCPeerConnection methods [`createOffer()`](https://w3c.github.io/webrtc-pc/#widl-RTCPeerConnection-createOffer-Promise-RTCSessionDescription--RTCOfferOptions-options)
and [`createAnswer()`](https://w3c.github.io/webrtc-pc/#widl-RTCPeerConnection-createAnswer-Promise-RTCSessionDescription--RTCAnswerOptions-options)
now require an error handler as well as a success handler. Previously it had
been possible to call these methods with only a success handler. That usage is
deprecated.

In Chrome 49 we've also added a warning if you call
[`setLocalDescription()`](https://w3c.github.io/webrtc-pc/#widl-RTCPeerConnection-setLocalDescription-Promise-void--RTCSessionDescriptionInit-description)
or [`setRemoteDescription()`](https://w3c.github.io/webrtc-pc/#widl-RTCPeerConnection-setRemoteDescription-Promise-void--RTCSessionDescriptionInit-description)
without supplying an error handler. We expect to make the error handler
argument mandatory for these methods in Chrome 50.

This is part of clearing the way for introducing promises on these methods,
as required by the [WebRTC spec](https://w3c.github.io/webrtc-pc/).

Here's an example from the WebRTC
[RTCPeerConnection demo](https://webrtc.github.io/samples/src/content/peerconnection/pc1/){: .external }
([main.js, line 126](https://github.com/webrtc/samples/blob/gh-pages/src/content/peerconnection/pc1/js/main.js#L126)):

    function onCreateOfferSuccess(desc) {
      pc1.setLocalDescription(desc, function() {
         onSetLocalSuccess(pc1);
      }, onSetSessionDescriptionError);
      pc2.setRemoteDescription(desc, function() {
        onSetRemoteSuccess(pc2);
      }, onSetSessionDescriptionError);
      pc2.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
    }

Note that both `setLocalDescription()` and `setRemoteDescription()` always had an error
handler parameter, so simply specifying that parameter is a safe change.

In general, for production WebRTC applications we recommend that you use
[`adapter.js`](https://github.com/webrtc/adapter),  a shim, maintained by the
WebRTC project, to insulate apps from spec changes and prefix differences.

## Document.defaultCharset is deprecated

**TL;DR**: [`Document.defaultCharset`](https://github.com/whatwg/dom/issues/58) has
been deprecated to improve spec compliance.

[Intent to Remove](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/dqlJguVuIHs)
[Chromestatus Tracker](https://www.chromestatus.com/features/5730982598541312)
[CRBug Issue](https://code.google.com/p/chromium/issues/detail?id=522100)

The `Document.defaultCharset` is a read-only property that returns the default
character encoding of the user's system based on their regional settings.  It's
not been found to be useful to maintain this value because of the way that
browsers use the character encoding information in the HTTP Response or in the
meta tag embedded in the page.

By using document.characterSet you will get the first value specified in the
HTTP header. If that is not present then you will get the value specified in the
`charset` attribute of the `<meta>` element (for example, `<meta charset="utf-8">`).
Finally if none of those are available the `document.characterSet` will be the
user's system setting.

Gecko has not supported this property and it is not cleanly specced so this
property will be deprecated from Blink in Chrome 49 (Beta in January 2016).  The
following warning will appear in your console until the removal of the property
in Chrome 50:

    'Document.defaultCharset' is deprecated and will be removed in M50, around
    April 2016. See
    https://www.chromestatus.com/features/6217124578066432 for more details.

More discussion of the reasoning not to spec this out can be read on github
[https://github.com/whatwg/dom/issues/58](https://github.com/whatwg/dom/issues/58)

## getStorageUpdates() removed

**TL;DR**: `Navigator.getStorageUpdates()` has been removed as it is no longer in the
[Navigator spec](https://developer.mozilla.org/en-US/docs/Web/API/Navigator).

[Intent to Remove](https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/ak1kVjiX9T4/mo1rqcyQAQAJ)
[Chromestatus Tracker](https://www.chromestatus.com/features/4780366799831040)
[CRBug Issue](https://code.google.com/p/chromium/issues/detail?id=465255)

If this impacts anyone I will eat my hat. `getStorageUpdates()` has hardly ever
(if at all) been used on the web.

To quote the (very old version) of the HTML5 spec:

> If a script uses the
> [`document.cookie`](https://www.w3.org/TR/2009/WD-html5-20090423/dom.html#dom-document-cookie)
> API, or the `localStorage` API, the browser will block other scripts from
> accessing cookies or storage until the first script finishes.
>
> Calling the
> [`navigator.getStorageUpdates()`](https://www.w3.org/TR/2009/WD-html5-20090423/browsers.html#dom-navigator-getstorageupdates)
> method tells the user agent to unblock any other scripts that may be blocked,
> even though the script hasn't returned.
>
> Values of cookies and items in the Storage objects of `localStorage` attributes
> can change after calling this method, whence its name.

Sounds pretty cool right? The spec even uses the word "whence" (which by
happenstance is the only instance of whence in the spec).  At the spec level
there was a `StorageMutex` that controlled access to blocking storage such as
`localStorage` and cookies, and this API would help free that mutex so other
scripts would not be blocked by this `StorageMutex`.  But it was never
implemented, it's not supported in IE or Gecko, and WebKit's (and thus Blink's)
implementation has been a no-op.

It's been removed from the specs for quite a while and has been removed
completely from Blink (for the longest time it has been a no-op and did
nothing even if called).

In the unlikely event that you had code that called `navigator.getStorageUpdates()`
then you will have to check for the presence of the function before calling it.

## Object.observe() is deprecated

**TL;DR**: `Object.observe()` has been deprecated as it is [no longer on the
standardization track](https://esdiscuss.org/topic/an-update-on-object-observe)
and will be removed in a future release.

[Intent to Remove](https://groups.google.com/forum/#!topic/v8-users/12NbuZ4BB7A)
[Chromestatus Tracker](https://www.chromestatus.com/features/6147094632988672)
[CRBug Issue](https://code.google.com/p/chromium/issues/detail?id=162553)

In November 2015 it was announced that [`Object.Observe` was being withdrawn from
TC39](https://esdiscuss.org/topic/an-update-on-object-observe).  It has been
deprecated from Chrome 49 and you will see the following warning in the console
if you try to use it:

    'Object.observe' is deprecated and will be removed in M50, around April
    2016. See
    https://www.chromestatus.com/features/6147094632988672 for more details.

Many developers liked this API and if you have been experimenting with it and
are now seeking a transition path, consider using a polyfill such as
[MaxArt2501/object-observe](https://github.com/MaxArt2501/object-observe) or a
wrapper library like
[polymer/observe-js](https://github.com/polymer/observe-js).

{% include "comment-widget.html" %}