[Q] how to receive Graphics Processing Unit (GPU) information - Java for Android App Development

I dug up the entire network and not found how to read the following data:
GRAPHICS PROCESSING UNIT
General Info:
Model: Mali-400 MP
Vendor: ARM
OpenGL Version: OpenGL ES 2.0
i try this:
Log.d("GL", "GL_RENDERER = " + gl.glGetString(GL10.GL_RENDERER));
Log.d("GL", "GL_VENDOR = " + gl.glGetString(GL10.GL_VENDOR));
Log.d("GL", "GL_VERSION = " + gl.glGetString(GL10.GL_VERSION));
Log.i("GL", "GL_EXTENSIONS = " + gl.glGetString(GL10.GL_EXTENSIONS));
but i dont know how to work with lg
How to initialize the variable ?
thanks

GoldSoft said:
I dug up the entire network and not found how to read the following data:
GRAPHICS PROCESSING UNIT
General Info:
Model: Mali-400 MP
Vendor: ARM
OpenGL Version: OpenGL ES 2.0
i try this:
Log.d("GL", "GL_RENDERER = " + gl.glGetString(GL10.GL_RENDERER));
Log.d("GL", "GL_VENDOR = " + gl.glGetString(GL10.GL_VENDOR));
Log.d("GL", "GL_VERSION = " + gl.glGetString(GL10.GL_VERSION));
Log.i("GL", "GL_EXTENSIONS = " + gl.glGetString(GL10.GL_EXTENSIONS));
but i dont know how to work with lg
How to initialize the variable ?
thanks
Click to expand...
Click to collapse
FYI, in order to get those info you have to render a GLSurfaceView.
You could do it this way:
Make a dedicated activity with the only purpose to catch the GPU info you need.
Better if the activity looks even translucent.
Code:
package com.my.fkn.pkg;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class TestGL extends Activity
{
GLSurfaceView mGLSurfaceView;
final Handler h = new Handler()
{
[user=439709]@override[/user]
public void handleMessage(Message msg)
{
if (msg.what == 0) { close( (String)msg.obj ); }
}
};
GLSurfaceView.Renderer renderer = new GLSurfaceView.Renderer()
{
[user=439709]@override[/user]
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
gl.glClearColor(8, 8, 8, 0);
String glInfo = gl.glGetString(GL10.GL_RENDERER);
glInfo = glInfo + "\n" + gl.glGetString(GL10.GL_VENDOR);
glInfo = glInfo + "\n" + gl.glGetString(GL10.GL_VERSION);
glInfo = glInfo + "\n" + gl.glGetString(GL10.GL_EXTENSIONS);
Message.obtain(h, 0, glInfo).sendToTarget();
}
[user=439709]@override[/user]
public void onSurfaceChanged(GL10 gl, int width, int height) { }
[user=439709]@override[/user]
public void onDrawFrame(GL10 gl) { }
};
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mGLSurfaceView = new GLSurfaceView(this);
mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
mGLSurfaceView.setRenderer(renderer);
setContentView(mGLSurfaceView);
}
public void close(String glInfo)
{
Intent intent= new Intent();
intent.putExtra("GLInfo", glInfo);
setResult(Activity.RESULT_OK, intent);
finish();
}
}
As you can see once the GLInfo has been collected the activity finishes, it's a matter of half a second.
Now, from your main activity:
Start the TestGL activity
Code:
private void startTestGLForGPUInfo()
{
Intent i = new Intent(MyMainActivity.this, TestGL.class);
startActivityForResult(i, GL_REQUEST_CODE);
}
and get the result
Code:
[user=439709]@override[/user]
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == GL_REQUEST_CODE)
{
if (resultCode == Activity.RESULT_OK)
{
String[] gi = intent.getStringExtra("GLInfo").split("\n");
String glRenderer = gi[0];
String glVendor = gi[1];
String glVersion = gi[2];
String glExtensions = gi[3];
}
}
}

thanks for the help
thanks for the help !
i try it but a got full of error
I hope it is not rude to ask,
can you send me any working program ?

GoldSoft said:
thanks for the help !
i try it but a got full of error
I hope it is not rude to ask,
can you send me any working program ?
Click to expand...
Click to collapse
I suspect you even don't know how to build your main activity, keep trying to fix those errors you'll learn a lot.
OK that was the hard way, the easy way is just below ready to download. It's a working mini app project.
Unzip and import the project in Eclipse, once ready run as Android application.
Regarding the code the interesting part (at least for your purpose) is all in the TestGL activity.

thanks !!!!!
thanks !!!!! its works !!!! :good:

Related

[Q] Shoutcast ICY to Http (Eclair compatible)

Hi.
I'm currently working on a wakeup-app (alarm) that plays your favorite radio-station via shoutcast-stream.
It looked really easy:
Code:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE);
mp.prepare();
mp.start();
Then I found out Eclair doesn't support shoutcast's ICY protocol. Grmbl.
So for 2.1 (and earlier versions) it is required to handle the shoutcast-stream seperatly and pass it to MediaPlayer via http.
I even found an example:
http://code.google.com/p/npr-android-app/source/browse/trunk/Npr/src/org/npr/android/news/StreamProxy.java
Problem is that it's all a bit too advanced for me, so I was wondering if anyone has a really simple example of how to do this?
Something like:
"Add 'this file' to your project (where 'this file' would be a class similarly to StreamProxy) and then add this to your application:"
Code:
StreamProxy sp = new StreamProxy();
sp.setDataSource( SHOUTCAST_URL );
MediaPlayer mp = new MediaPlayer();
mp.setDataSource( sp.getProxyUrl );
mp.prepare();
mp.start();
(Pardon my english
fixed!
Will post how I did it soon.
Here's the app:
http://android.rejh.nl/fmalarm
Just got reminded by someone that I never posted the solution. Here goes:
Code:
// Streamurl
String streamUrl = "[Path-to-audio-stream-or-file]";
// Prepare Proxy (for Android 2.1 en lower (sdk<8))
sdkVersion = 0;
try { sdkVersion = Integer.parseInt(Build.VERSION.SDK); } // Note: Build.VERSION.SDK is deprecated..
catch (NumberFormatException e) {}
if (sdkVersion<8) {
if (proxy==null) {
try {
proxy = new StreamProxy();
proxy.init();
proxy.start();
streamUrl = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), url);
} catch(IllegalStateException e) { Log.e(LOGTAG," -> IllStateException: "+e, e); }
}
}
// Create mediaplayer and set stream (proxied if needed)
mp = new MediaPlayer();
mp.setDataSource(streamUrl);
UPDATE!! Forgot the StreamProxy code
Code:
// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Minor changes by REJH Gadellaa 2010/2011
package org.npr.android.news;
import android.util.Log;
import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseFactory;
import org.apache.http.ParseException;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.OperatedClientConnection;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.DefaultClientConnection;
import org.apache.http.impl.conn.DefaultClientConnectionOperator;
import org.apache.http.impl.conn.DefaultResponseParser;
import org.apache.http.impl.conn.SingleClientConnManager;
import org.apache.http.io.HttpMessageParser;
import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicLineParser;
import org.apache.http.message.ParserCursor;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.CharArrayBuffer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
public class StreamProxy implements Runnable {
private static final String LOG_TAG = "FMA2Proxy";
private int port = 5050;
public int getPort() {
return port;
}
private boolean isRunning = true;
private ServerSocket socket;
private Thread thread;
public void init() {
try {
socket = new ServerSocket(port, 0, InetAddress.getByAddress(new byte[] {127,0,0,1}));
socket.setSoTimeout(5000);
port = socket.getLocalPort();
Log.d(LOG_TAG, "port " + port + " obtained");
} catch (UnknownHostException e) {
Log.e(LOG_TAG, "Error initializing server", e);
} catch (IOException e) {
Log.e(LOG_TAG, "Error initializing server", e);
}
}
public void start() {
if (socket == null) {
throw new IllegalStateException("Cannot start proxy; it has not been initialized.");
}
thread = new Thread(this);
thread.start();
}
public void stop() {
isRunning = false;
if (thread == null) {
throw new IllegalStateException("Cannot stop proxy; it has not been started.");
}
if (socket!=null) { try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
thread.interrupt();
try {
thread.join(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// @Override
public void run() {
Log.d(LOG_TAG, "running");
while (isRunning) {
try {
Socket client = socket.accept();
if (client == null) {
continue;
}
Log.d(LOG_TAG, "client connected");
HttpRequest request = readRequest(client);
processRequest(request, client);
} catch (SocketTimeoutException e) {
// Do nothing
} catch (IOException e) {
Log.e(LOG_TAG, "Error connecting to client", e);
}
}
Log.d(LOG_TAG, "Proxy interrupted. Shutting down.");
}
private HttpRequest readRequest(Socket client) {
HttpRequest request = null;
InputStream is;
String firstLine;
try {
is = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
firstLine = reader.readLine();
} catch (IOException e) {
Log.e(LOG_TAG, "Error parsing request", e);
return request;
}
if (firstLine == null) {
Log.i(LOG_TAG, "Proxy client closed connection without a request.");
return request;
}
StringTokenizer st = new StringTokenizer(firstLine);
String method = st.nextToken();
String uri = st.nextToken();
Log.d(LOG_TAG, uri);
String realUri = uri.substring(1);
Log.d(LOG_TAG, realUri);
request = new BasicHttpRequest(method, realUri);
return request;
}
private HttpResponse download(String url) {
DefaultHttpClient seed = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
registry.register(
new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
SingleClientConnManager mgr = new MyClientConnManager(seed.getParams(),
registry);
DefaultHttpClient http = new DefaultHttpClient(mgr, seed.getParams());
HttpGet method = new HttpGet(url);
HttpResponse response = null;
try {
Log.d(LOG_TAG, "starting download");
response = http.execute(method);
Log.d(LOG_TAG, "downloaded");
} catch (ClientProtocolException e) {
Log.e(LOG_TAG, "Error downloading", e);
} catch (IOException e) {
Log.e(LOG_TAG, "Error downloading", e);
}
return response;
}
private void processRequest(HttpRequest request, Socket client)
throws IllegalStateException, IOException {
if (request == null) {
return;
}
Log.d(LOG_TAG, "processing");
String url = request.getRequestLine().getUri();
HttpResponse realResponse = download(url);
if (realResponse == null) {
return;
}
Log.d(LOG_TAG, "downloading...");
InputStream data = realResponse.getEntity().getContent();
StatusLine line = realResponse.getStatusLine();
HttpResponse response = new BasicHttpResponse(line);
response.setHeaders(realResponse.getAllHeaders());
Log.d(LOG_TAG, "reading headers");
StringBuilder httpString = new StringBuilder();
httpString.append(response.getStatusLine().toString());
httpString.append("\n");
for (Header h : response.getAllHeaders()) {
httpString.append(h.getName()).append(": ").append(h.getValue()).append(
"\n");
}
httpString.append("\n");
Log.d(LOG_TAG, "headers done");
try {
byte[] buffer = httpString.toString().getBytes();
int readBytes = -1;
Log.d(LOG_TAG, "writing to client");
client.getOutputStream().write(buffer, 0, buffer.length);
// Start streaming content.
byte[] buff = new byte[1024 * 50];
while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) {
client.getOutputStream().write(buff, 0, readBytes);
}
} catch (Exception e) {
Log.e("", e.getMessage(), e);
} finally {
if (data != null) {
data.close();
}
client.close();
}
}
private class IcyLineParser extends BasicLineParser {
private static final String ICY_PROTOCOL_NAME = "ICY";
private IcyLineParser() {
super();
}
@Override
public boolean hasProtocolVersion(CharArrayBuffer buffer,
ParserCursor cursor) {
boolean superFound = super.hasProtocolVersion(buffer, cursor);
if (superFound) {
return true;
}
int index = cursor.getPos();
final int protolength = ICY_PROTOCOL_NAME.length();
if (buffer.length() < protolength)
return false; // not long enough for "HTTP/1.1"
if (index < 0) {
// end of line, no tolerance for trailing whitespace
// this works only for single-digit major and minor version
index = buffer.length() - protolength;
} else if (index == 0) {
// beginning of line, tolerate leading whitespace
while ((index < buffer.length()) &&
HTTP.isWhitespace(buffer.charAt(index))) {
index++;
}
} // else within line, don't tolerate whitespace
if (index + protolength > buffer.length())
return false;
return buffer.substring(index, index + protolength).equals(ICY_PROTOCOL_NAME);
}
@Override
public Header parseHeader(CharArrayBuffer buffer) throws ParseException {
return super.parseHeader(buffer);
}
@Override
public ProtocolVersion parseProtocolVersion(CharArrayBuffer buffer,
ParserCursor cursor) throws ParseException {
if (buffer == null) {
throw new IllegalArgumentException("Char array buffer may not be null");
}
if (cursor == null) {
throw new IllegalArgumentException("Parser cursor may not be null");
}
final int protolength = ICY_PROTOCOL_NAME.length();
int indexFrom = cursor.getPos();
int indexTo = cursor.getUpperBound();
skipWhitespace(buffer, cursor);
int i = cursor.getPos();
// long enough for "HTTP/1.1"?
if (i + protolength + 4 > indexTo) {
throw new ParseException
("Not a valid protocol version: " +
buffer.substring(indexFrom, indexTo));
}
// check the protocol name and slash
if (!buffer.substring(i, i + protolength).equals(ICY_PROTOCOL_NAME)) {
return super.parseProtocolVersion(buffer, cursor);
}
cursor.updatePos(i + protolength);
return createProtocolVersion(1, 0);
}
@Override
public RequestLine parseRequestLine(CharArrayBuffer buffer,
ParserCursor cursor) throws ParseException {
return super.parseRequestLine(buffer, cursor);
}
@Override
public StatusLine parseStatusLine(CharArrayBuffer buffer,
ParserCursor cursor) throws ParseException {
StatusLine superLine = super.parseStatusLine(buffer, cursor);
return superLine;
}
}
class MyClientConnection extends DefaultClientConnection {
@Override
protected HttpMessageParser createResponseParser(
final SessionInputBuffer buffer,
final HttpResponseFactory responseFactory, final HttpParams params) {
return new DefaultResponseParser(buffer, new IcyLineParser(),
responseFactory, params);
}
}
class MyClientConnectionOperator extends DefaultClientConnectionOperator {
public MyClientConnectionOperator(final SchemeRegistry sr) {
super(sr);
}
@Override
public OperatedClientConnection createConnection() {
return new MyClientConnection();
}
}
class MyClientConnManager extends SingleClientConnManager {
private MyClientConnManager(HttpParams params, SchemeRegistry schreg) {
super(params, schreg);
}
@Override
protected ClientConnectionOperator createConnectionOperator(
final SchemeRegistry sr) {
return new MyClientConnectionOperator(sr);
}
}
}

How SEUS Flashing Works

OK, so been trying to figure out what happens when you use SEUS.
It checks for internet connection by loading this URL:
Code:
http://emma.extranet.sonyericsson.com/ns/no-cache
I've figured out quite a bit.
Sony Ericsson has implemented something called Tampered Device Service.
This checks if the devices has been tampered with.
This service works from this server:
Code:
tds.sonyericsson.com
Then for the actual firmware download.
This is done by downloading 2 *.ser.gz which tells SEUS what Software customization to get and is sessions specific.
The customization ser.gz file looks something like this:
Code:
CDA=1233-7027_NjKhzOzTUsfXvPg40lyh6aTl.ser.gz
And it's downloaded from:
Code:
emma.extranet.sonyericsson.com
It's done via some sort of search mechanism on the server.
That looks like this:
Code:
ns/usdoe1/2/script/search/TAC8=35941903/CDA=1233-7027_By5JACZqd1R7JOpLu6qvwK8N.ser.gz
After that it's downloading the actual firmware files.
They are downloaded in bin format which I haven't been able to unpack yet.
They are also downloaded from the emma server and is named something like:
Code:
277795427_k9ABo3YVh+8klYUKwllGLDcJ.bin - ~14.3 MB
277835617_ZpJseUr9e09U5h2Cz81+5vcT.bin ~149 MB
Then it does a netbios call which has some sort of HEX code.
And then check the Internet connection again:
Code:
http://emma.extranet.sonyericsson.com/ns/no-cache
Now it starts up a service called:
Code:
/fq/ServiceClientDbServlet
This service runs from this server:
Code:
ma3.extranet.sonyericsson.com
This last part is done twice in a row.
Inside one of the *ser.gz files is a *.ser file which contains some code and instructions. Some parts is encrypted but most of the code is not.
See the complete code in post #2
I don't quite know what to do with all this info yet.
But hopefully something useful will come of this.
Just wanted to share a bit of my knowledge, hope it's useful for some of you here.
Code:
import com.sonyericsson.cs.ma.tess.api.ServiceException;
import com.sonyericsson.cs.ma.tess.api.ServiceRuntimeException;
import com.sonyericsson.cs.ma.tess.api.TessFile;
import com.sonyericsson.cs.ma.tess.api.UI;
import com.sonyericsson.cs.ma.tess.api.device.IdentificationResult;
import com.sonyericsson.cs.ma.tess.api.inject.InjectConfigValue;
import com.sonyericsson.cs.ma.tess.api.inject.InjectRef;
import com.sonyericsson.cs.ma.tess.api.inject.IncludeFor;
import com.sonyericsson.cs.ma.tess.api.inject.ServiceMethod;
import com.sonyericsson.cs.ma.tess.api.logging.Logging;
import com.sonyericsson.cs.ma.tess.api.protocols.DataArea;
import com.sonyericsson.cs.ma.tess.api.protocols.ProtocolFactory;
import com.sonyericsson.cs.ma.tess.api.protocols.VersionResponse;
import com.sonyericsson.cs.ma.tess.api.protocols.s1.S1Protocol;
import com.sonyericsson.cs.ma.tess.api.protocols.s1.S1Protocol.ShutdownMode;
import com.sonyericsson.cs.ma.tess.api.secs.SECSUnitData;
import com.sonyericsson.cs.ma.tess.api.secs.SECSUtil;
import com.sonyericsson.cs.ma.tess.api.service.ServiceResult;
import com.sonyericsson.cs.ma.tess.api.service.ServiceResultType;
import com.sonyericsson.cs.ma.tess.api.service.ServiceType;
import com.sonyericsson.cs.ma.tess.api.statistics.DiagnosticsUtil;
import com.sonyericsson.cs.ma.tess.api.statistics.StatisticsUtil;
import com.sonyericsson.cs.ma.tess.api.statistics.StatisticsUtil.SoftwareComponent;
import com.sonyericsson.cs.ma.tess.api.ta.TAUnit;
import com.sonyericsson.cs.ma.tess.api.util.StringUtil;
import com.sonyericsson.cs.ma.tess.api.x10.MarlinCertificateUpdate;
import com.sonyericsson.cs.ma.tess.api.zip.ZipFileUtil;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Document;
/**
* S1 QSD8250 eSheep platform Main Services implementation.
*
* Services in this logic implemented for use in COMMERCIAL services!
*
*/
public class S1QSD8250eSheepMainServicesLIVE
{
@InjectRef
private ProtocolFactory aProtocolFactory;
@InjectRef
private UI aUI;
@InjectRef
private Logging aLogger;
@InjectRef
private IdentificationResult aIdentifiers;
@InjectRef
private ZipFileUtil aZipFileUtil;
@InjectRef
private static DiagnosticsUtil aDiagnostics;
@InjectRef
private StatisticsUtil aStatistics;
@InjectRef
private SECSUtil aSECS;
@InjectRef
private StringUtil aStringUtil;
@InjectRef
private ClientEnvironment aClientEnvironment;
@InjectRef
private MarlinCertificateUpdate marlinCertUpdate;
// File references
// Loader reference
@InjectConfigValue("cLOADER")
private TessFile aLoader;
// App-SW reference - Exclude from Activation
@IncludeFor([ServiceType.CUSTOMIZE, ServiceType.SOFTWARE_UPDATE,
ServiceType.SOFTWARE_UPDATE_CONTENT_REFRESH])
@InjectConfigValue("cAPP_SW")
private TessFile aAppSW;
// FSP Reference - Exclude from Activation
@IncludeFor([ServiceType.CUSTOMIZE, ServiceType.SOFTWARE_UPDATE,
ServiceType.SOFTWARE_UPDATE_CONTENT_REFRESH])
@InjectConfigValue("cFSP")
private TessFile aFSP;
// miscTA units
// Startup/Shutdown flag used for indicating successful flash.
@InjectConfigValue("cTA_FLASH_STARTUP_SHUTDOWN_RESULT")
private String aStrTaFlashStartShutdownResult;
// Startup/Shutdown flag used for indicating successful flash.
@InjectConfigValue("cTA_EDREAM_FLASH_IN_PROGRESS")
private String aStrTaEDreamFlashStartShutdownResult;
// SIMlock data unit
@InjectConfigValue("cTA_SIMLOCK_DATA")
private String aStrTaSimlockData;
// Loose temp data unit
@InjectConfigValue("cTA_LOOSE_TEMP")
private String aStrTaLooseTemp;
// TA_APPLICATION_BUFFER_DATA_ARRAY[2]
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY2")
private String aStrTaApplicationBufferDataArray2;
// TA_APPLICATION_BUFFER_DATA_ARRAY[3]
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY3")
private String aStrTaApplicationBufferDataArray3;
// TA_MARLIN_DRM_KEY_UPDATE_FLAG
@InjectConfigValue("cTA_MARLIN_DRM_KEY_UPDATE_FLAG")
private String aStrTaMarlinDRMKeyUpdateFlag;
// Parameter names
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY0_NAME")
private String aTaApplicationBufferDataArray0Name;
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY1_NAME")
private String aTaApplicationBufferDataArray1Name;
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY2_NAME")
private String aTaApplicationBufferDataArray2Name;
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY3_NAME")
private String aTaApplicationBufferDataArray3Name;
@InjectConfigValue("cTA_SIMLOCK_DATA_NAME")
private String aTaSimlockDataName;
@InjectConfigValue("cTA_LOOSE_TEMP_NAME")
private String aTaLooseTempName;
@InjectConfigValue("cVERSION_RESPONSE")
private String aVersionResponseName;
// miscTA unit values
// Startup/Shutdown flag, cTA_FLASH_STARTUP_SHUTDOWN_RESULT, values
@InjectConfigValue("cTA_FLASH_STARTUP_SHUTDOWN_RESULT_ONGOING_VALUE")
private String aTaFlashStartupShutdownResultOngoingValue;
@InjectConfigValue("cTA_FLASH_STARTUP_SHUTDOWN_RESULT_FINISHED_VALUE")
private String aTaFlashStartupShutdownResultFinishedValue;
// Startup/Shutdown flag, cTA_EDREAM_FLASH_STARTUP_SHUTDOWN_RESULT, values
@InjectConfigValue("cTA_EDREAM_FLASH_FLASH_IN_PROGRESS_ONGOING")
private String aTaEDreamFlashStartupShutdownResultOngoingValue;
@InjectConfigValue("cTA_EDREAM_FLASH_FLASH_IN_PROGRESS_COMPLETED")
private String aTaEDreamFlashStartupShutdownResultFinishedValue;
// Update.xml values
// File name
private static String UPDATE_XML_FILE_NAME = "update.xml";
// NOERASE tag value
private static String UPDATE_XML_NOERASE_TAG = "NOERASE";
// SIMLOCK tag value
private static String UPDATE_XML_SIMLOCK_TAG = "SIMLOCK";
// PRESERVECACHE tag value
private static String UPDATE_XML_PRESERVECACHE_TAG = "PRESERVECACHE";
// UI Progress texts
@InjectConfigValue("cSEND_DATA")
private String aSendDataText;
@InjectConfigValue("cSEND_DATA_DONE")
private String aSendDataDoneText;
@InjectConfigValue("cSERVICE_FINALIZING")
private String aServiceFinalizingText;
@InjectConfigValue("cSERVICE_FINALIZING_DONE")
private String aServiceFinalizingDoneText;
@InjectConfigValue("cSERVICE_INITIALIZATION")
private String aServiceInitializationText;
@InjectConfigValue("cSERVICE_INITIALIZATION_DONE")
private String aServiceInitializationDoneText;
/**
* ACTIVATION
*
*/
@ServiceMethod(ServiceType.ACTIVATION)
public ServiceResult activation() throws ServiceException
{
boolean vDoActivation = true;
showInitServiceText();
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
int vTaLooseTemp = Integer.parseInt(aStrTaLooseTemp);
int vTaApplicationBufferDataArray2 =
Integer.parseInt(aStrTaApplicationBufferDataArray2);
int vTaApplicationBufferDataArray3 =
Integer.parseInt(aStrTaApplicationBufferDataArray3);
// Check if activation is needed?
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
// Read the SIMlock data from TA_SIMLOCK_DATA
byte[] vSIMlockData = vS1.readDataArea(vTaSimlockData);
if (vSIMlockData != null && vSIMlockData.length >= 20)
{
// Check 20 first bytes (if set to 0)
for (int vI = 0; vI < 20; vI++)
{
if (vSIMlockData[vI] != 0)
{
vDoActivation = false;
break;
}
}
}
else
{
aLogger
.error("Could not determine if activation is needed. Not possible to read enough data.");
throw new ServiceRuntimeException("Error when activating phone.");
}
// Do activation?
if (vDoActivation)
{
// Verify that the dongle is present
aSECS.ensureDongleReady();
String vIMEI = aIdentifiers.getIMEI();
SECSUnitData[] vInputData = getS1SIMLockSignatureInputData(vS1);
SECSUnitData[] vOutputData =
vS1.getS1SIMLockSignature(vInputData, vIMEI);
if (vOutputData != null && vOutputData.length > 6)
{
byte[] vEmpty = new byte[1];
vEmpty[0] = 0x00;
vS1.writeToDataArea(vTaApplicationBufferDataArray2, vEmpty);
vS1.writeToDataArea(
vTaApplicationBufferDataArray3,
vOutputData[3].getUnitData());
vS1
.writeToDataArea(vTaSimlockData, vOutputData[4]
.getUnitData());
vS1.writeToDataArea(vTaLooseTemp, vOutputData[5].getUnitData());
}
else
{
aLogger.error("Not enough data in response from SECS server.");
throw new ServiceRuntimeException(
"Error occured when communicating with server.");
}
}
else
{
aUI
.showText("ACTIVATION NOT NEEDED! This unit has been "
+ "activated already. The service is exiting without execution.");
}
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
}
catch (ServiceException pEx)
{
aLogger.error("Exception when executing ACTIVATION service.", pEx);
throw pEx;
}
return ServiceResult.SUCCESSFUL;
}
/**
* CUSTOMIZE
*
*/
@ServiceMethod(ServiceType.CUSTOMIZE)
public ServiceResult customize() throws ServiceException
{
showInitServiceText();
ServiceResult vServiceResult =
new ServiceResult(
ServiceResultType.SUCCESSFUL,
"Customize EXECUTED! ACTIVATION NEEDED!",
null);
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
int vTaLooseTemp = Integer.parseInt(aStrTaLooseTemp);
showSendingDataText();
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
readDID(vS1);
updateMartinKey(vS1);
setFlashStartupShutdownFlagOngoing(vS1);
// Send App-SW
sendFile(vS1, aAppSW);
// Send FSP
if ("false".equalsIgnoreCase(aFSP.getProperty("SIMLockCustomized"))
&& "true".equalsIgnoreCase(aIdentifiers
.getIdentifier("SIMLockReusable")))
{
// quick-customize
String[] vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_SIMLOCK_TAG;
String[] vFilesToExcludeFromFSP = parseFile(aFSP, vExcludeTags);
// Send FSP
sendZipFile(vS1, aFSP, vFilesToExcludeFromFSP);
vServiceResult =
new ServiceResult(
ServiceResultType.SUCCESSFUL,
"Quick Customize EXECUTED! NO ACTIVATION NEEDED!",
null);
}
else
{
// customize
// Tamper the simlock data
tamperSimlockData(vS1);
// Set the simlock data unit id to loose temp
aFSP.modifyData(vTaSimlockData, vTaLooseTemp);
sendFile(vS1, aFSP);
}
setFlashStartupShutdownFlagFinished(vS1);
showSendingDataTextDone();
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
storeSoftwareAfterStatistics();
}
catch (ServiceException pEx)
{
aLogger.error("Exception when executing CUSTOMIZE service.", pEx);
throw pEx;
}
return vServiceResult;
}
/**
* SOFTWARE UPDATE
*
*/
@ServiceMethod(ServiceType.SOFTWARE_UPDATE)
public ServiceResult softwareUpdate() throws ServiceException
{
showInitServiceText();
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
showSendingDataText();
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
readDID(vS1);
updateMartinKey(vS1);
// Search the APP-SW zip file for xml file and metadata. Exclude user
// data
String[] vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_NOERASE_TAG;
String[] vFilesToExcludeFromAPPSW = parseFile(aAppSW, vExcludeTags);
// Search the FSP zip file for xml file and metadata. Exclude user data
// and simlock if existing
vExcludeTags = new String[2];
vExcludeTags[0] = UPDATE_XML_NOERASE_TAG;
vExcludeTags[1] = UPDATE_XML_SIMLOCK_TAG;
String[] vFilesToExcludeFromFSP = parseFile(aFSP, vExcludeTags);
setFlashStartupShutdownFlagOngoing(vS1);
// Send App-SW
// Anything to exclude?
if (vFilesToExcludeFromAPPSW != null
&& vFilesToExcludeFromAPPSW.length > 0)
{
sendZipFile(vS1, aAppSW, vFilesToExcludeFromAPPSW);
}
else
{
sendFile(vS1, aAppSW);
}
// Send FSP
sendZipFile(vS1, aFSP, vFilesToExcludeFromFSP);
setFlashStartupShutdownFlagFinished(vS1);
showSendingDataTextDone();
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
storeSoftwareAfterStatistics();
}
catch (ServiceException pEx)
{
aLogger
.error("Exception when executing SOFTWARE UPDATE service.", pEx);
throw pEx;
}
return ServiceResult.SUCCESSFUL;
}
/**
* SOFTWARE UPDATE CONTENT REFRESH
*
*/
@ServiceMethod(ServiceType.SOFTWARE_UPDATE_CONTENT_REFRESH)
public ServiceResult softwareUpdateContentRefresh() throws ServiceException
{
showInitServiceText();
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
showSendingDataText();
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
readDID(vS1);
updateMartinKey(vS1);
// Search the FSP zip file for xml file and metadata. Exclude
// simlock if existing
String[] vExcludeTags = new String[0];
aLogger.debug("isSwapEnabled is: "
+ aClientEnvironment.isSwapEnabled());
// Check the client environment.
if (!aClientEnvironment.isSwapEnabled())
{
aLogger.debug("Cache partition will be preserved.");
vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_PRESERVECACHE_TAG;
}
// Temporarily catch the exception
String[] vFilesToExcludeFromAPPSW = parseFile(aAppSW, vExcludeTags);
vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_SIMLOCK_TAG;
String[] vFilesToExcludeFromFSP = parseFile(aFSP, vExcludeTags);
setFlashStartupShutdownFlagOngoing(vS1);
// Anything to exclude?
if (vFilesToExcludeFromAPPSW != null
&& vFilesToExcludeFromAPPSW.length > 0)
{
sendZipFile(vS1, aAppSW, vFilesToExcludeFromAPPSW);
}
else
{
sendFile(vS1, aAppSW);
}
// Send FSP
sendZipFile(vS1, aFSP, vFilesToExcludeFromFSP);
setFlashStartupShutdownFlagFinished(vS1);
showSendingDataTextDone();
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
storeSoftwareAfterStatistics();
}
catch (ServiceException pEx)
{
aLogger
.error(
"Exception when executing SOFTWARE UPDATE CONTENT REFRESH service.",
pEx);
throw pEx;
}
return ServiceResult.SUCCESSFUL;
}
/**
* Private help method to get DID data from device, if available.
*
*/
private void readDID(S1Protocol pS1)
{
byte[] vEmptyUnit = new byte[0];
List<TAUnit> vUnits = new ArrayList<TAUnit>();
aLogger.debug("Reading diagnostic data.");
final int vLastUnit = 10009;
final int vFirstUnit = 10000;
for (int vUnit = vFirstUnit; vUnit <= vLastUnit; vUnit++)
{
try
{
byte[] vData = pS1.readDataArea(vUnit);
if (vData != null && vData.length > 0)
{
pS1.writeToDataArea(vUnit, vEmptyUnit);
vUnits.add(new TAUnit(vUnit, vData));
}
}
catch (ServiceException vServiceException)
{
}
}
if (vUnits.size() > 0)
{
byte[] vDiagnosticData;
try
{
aLogger.debug("Diagnostic data found, sending diagnostic data.");
vDiagnosticData = aDiagnostics.createDiagnosticData(vUnits);
aDiagnostics.storeDiagnostic(aIdentifiers.getIMEI(), aIdentifiers
.getApplicationSoftwareID(), aIdentifiers
.getApplicationSoftwareRev(), vDiagnosticData, "06");
}
catch (ServiceException pEx)
{
}
}
}
/**
* Private help method to tamper the simlock data.
*
*/
private void tamperSimlockData(S1Protocol pS1) throws ServiceException
{
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
// Read the SIMlock data from TA_SIMLOCK_DATA
byte[] vSIMlockData = pS1.readDataArea(vTaSimlockData);
if (vSIMlockData != null && vSIMlockData.length > 0)
{
// Tamper 20 first bytes (set to 0)
// Make sure enough data is read
if (vSIMlockData.length >= 20)
{
for (int vI = 0; vI < 20; vI++)
{
vSIMlockData[vI] = 0;
}
}
else
{
throw new ServiceRuntimeException(
"Data read, but not enough to tamper.");
}
// Write back the tampered SIMlock data to TA_SIMLOCK_DATA
pS1.writeToDataArea(vTaSimlockData, vSIMlockData);
}
else
{
throw new ServiceRuntimeException("Could not read data.");
}
}
/**
* Private help method to get S1 SIMlock signature input data from device.
*
*/
private SECSUnitData[] getS1SIMLockSignatureInputData(S1Protocol pS1)
throws ServiceException
{
SECSUnitData[] vSECSUnitData = new SECSUnitData[7];
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
int vTaLooseTemp = Integer.parseInt(aStrTaLooseTemp);
int vTaApplicationBufferDataArray3 =
Integer.parseInt(aStrTaApplicationBufferDataArray3);
byte[] vEmpty = new byte[1];
vEmpty[0] = 0x00;
vSECSUnitData[0] =
new SECSUnitData(aTaApplicationBufferDataArray0Name, vEmpty);
vSECSUnitData[1] =
new SECSUnitData(aTaApplicationBufferDataArray1Name, vEmpty);
vSECSUnitData[2] =
new SECSUnitData(aTaApplicationBufferDataArray2Name, vEmpty);
byte[] vInputUnitData = pS1.readDataArea(vTaApplicationBufferDataArray3);
vSECSUnitData[3] =
new SECSUnitData(aTaApplicationBufferDataArray3Name, vInputUnitData);
vInputUnitData = pS1.readDataArea(vTaSimlockData);
vSECSUnitData[4] = new SECSUnitData(aTaSimlockDataName, vInputUnitData);
vInputUnitData = pS1.readDataArea(vTaLooseTemp);
vSECSUnitData[5] = new SECSUnitData(aTaLooseTempName, vInputUnitData);
VersionResponse vVersionResponse = pS1.getVersionResponse();
byte[] vVersionResponseArray =
vVersionResponse.getVersionResponseAsBytes();
vInputUnitData = vVersionResponseArray;
vSECSUnitData[6] = new SECSUnitData(aVersionResponseName, vInputUnitData);
return vSECSUnitData;
}
/**
* Parses the specified file for a xml metadata file and the parses the xml
* file for the tags defined. Tag values are then returned as a string array.
*
*/
private String[] parseFile(TessFile pFile, String[] pTags)
throws ServiceException
{
ArrayList<String> vResult = new ArrayList<String>();
Document vUpdateXML =
aZipFileUtil.getXMLFile(pFile, UPDATE_XML_FILE_NAME);
if (vUpdateXML != null)
{
if (pTags != null)
{
for (String vTag : pTags)
{
String[] vFilesFound =
aZipFileUtil.getXMLTextContentByTagName(vUpdateXML, vTag);
if (vFilesFound != null && vFilesFound.length > 0)
{
aLogger.debug("Found files to exclude from "
+ pFile.getFileName()
+ " from tag "
+ vTag
+ " in "
+ UPDATE_XML_FILE_NAME
+ ":");
for (String vFileName : vFilesFound)
{
aLogger.debug(vFileName);
}
vResult.addAll(Arrays.asList(vFilesFound));
}
}
}
}
else
{
aLogger.debug("No " + UPDATE_XML_FILE_NAME + " found");
// throw new
throw new ServiceRuntimeException("Could not find a "
+ UPDATE_XML_FILE_NAME
+ " in the zip file, abort.");
}
return vResult.toArray(new String[vResult.size()]);
}
private void updateMartinKey(S1Protocol pS1) throws ServiceException
{
int vTaMarlinDRMKeyUpdateFlag =
Integer.parseInt(aStrTaMarlinDRMKeyUpdateFlag);
byte[] vFlagValue = null;
pS1.openDataArea(DataArea.MISC_TA);
// check the flag
try
{
vFlagValue = pS1.readDataArea(vTaMarlinDRMKeyUpdateFlag);
if (vFlagValue != null
&& aStringUtil
.convertByteArrayToString(vFlagValue)
.equalsIgnoreCase("01"))
{
// updated already
return;
}
}
catch (ServiceException vServiceException)
{
// exception indicates no update has been done
}
// check if update is available for this unit
if (marlinCertUpdate.isNewCertificateAvailable())
{
// update the cert
InputStream vTAFileInputStream =
marlinCertUpdate.getCertificateTAInputStream();
pS1.sendTAFileFromStream(vTAFileInputStream);
aLogger.debug("Marlin key updated.");
}
// set the flag as updated
pS1.writeToDataArea(vTaMarlinDRMKeyUpdateFlag, aStringUtil
.convertStringToByteArray("0x01"));
return;
}
/**
* Private help method to set the flash ongoing flag to ongoing.
*
* @throws ServiceException
*
*/
private void setFlashStartupShutdownFlagOngoing(S1Protocol pS1)
throws ServiceException
{
int vTaFlashStartupShutdownResult =
Integer.parseInt(aStrTaFlashStartShutdownResult);
int vTaEDreamFlashStartupShutdownResult =
Integer.parseInt(aStrTaEDreamFlashStartShutdownResult);
// Set the TA_FLASH_STARTUP_SHUTDOWN_RESULT (2227) flag to 0xA0000000 to
// indicate
// flash ongoing
pS1
.writeToDataArea(
vTaFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaFlashStartupShutdownResultOngoingValue));
// Set the 10100 flag specific for eDream
// Set the TA_EDREAM_FLASH_STARTUP_SHUTDOWN_RESULT (10100) flag to 0x01 to
// indicate
// flash ongoing
pS1
.writeToDataArea(
vTaEDreamFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaEDreamFlashStartupShutdownResultOngoingValue));
}
/**
* Private help method to set the flash ongoing flag to finished.
*
* @throws ServiceException
*
*/
private void setFlashStartupShutdownFlagFinished(S1Protocol pS1)
throws ServiceException
{
int vTaFlashStartupShutdownResult =
Integer.parseInt(aStrTaFlashStartShutdownResult);
int vTaEDreamFlashStartupShutdownResult =
Integer.parseInt(aStrTaEDreamFlashStartShutdownResult);
// Set the TA_FLASH_STARTUP_SHUTDOWN_RESULT (2227) flag to 0xAA000000 to
// indicate
// flash finished
pS1
.writeToDataArea(
vTaFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaFlashStartupShutdownResultFinishedValue));
// Set the 10100 flag specific for eDream
// Set the TA_EDREAM_FLASH_STARTUP_SHUTDOWN_RESULT (10100) flag to 0x00 to
// indicate flash finished
pS1
.writeToDataArea(
vTaEDreamFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaEDreamFlashStartupShutdownResultFinishedValue));
}
/**
* Private help method to store software and CDF ids and versions.
*
*/
private void storeSoftwareAfterStatistics()
{
String vAPPSWId = aAppSW.getProperty("Id");
String vAPPSWVer = aAppSW.getVersion();
String vCDFId = aFSP.getProperty("CDFId");
String vCDFVer = aFSP.getProperty("CDFVer");
if (vAPPSWId != null)
{
aStatistics.storeSoftwareAfter(
SoftwareComponent.SW1,
vAPPSWId,
vAPPSWVer);
}
if (vCDFId != null)
{
aStatistics.storeCustomizationAfter(vCDFId, vCDFVer);
}
}
private void sendZipFile(
S1Protocol pS1,
TessFile pFile,
String[] pFilesToExclude) throws ServiceException
{
aLogger.debug("Sending "
+ pFile.getFileName()
+ ", "
+ pFile.getVersion());
pS1.sendZipFile(pFile, pFilesToExclude);
}
private void sendFile(S1Protocol pS1, TessFile pFile)
throws ServiceException
{
aLogger.debug("Sending "
+ pFile.getFileName()
+ ", "
+ pFile.getVersion());
pS1.sendFile(pFile);
}
/**
* Private help method to display start sending data text.
*
*/
private void showSendingDataText()
{
aUI.showText(aSendDataText);
}
/**
* Private help method to display start sending data done text.
*
*/
private void showSendingDataTextDone()
{
aUI.showText(aSendDataDoneText);
}
/**
* Private help method to display start up and initialization text.
*
*/
private void showInitServiceText()
{
aUI.showText(aServiceInitializationText);
aUI.showText(aServiceInitializationDoneText);
aUI.showText("");
}
/**
* Private help method to display please wait text.
*
*/
private void showFinalizingText()
{
aUI.showText("");
aUI.showText(aServiceFinalizingText);
aUI.showText(aServiceFinalizingDoneText);
}
}
Reserved for future use.
wow seems u done some packet sniffing...
may be u should contact Bin4ry regarding this... he is involved in FreeXperia Project for Arc/Play...
i am sure he can shed some more light on this matter...
Figured out the *.bin files is the actual files that also goes in the blob_fs folder:
Code:
%programfiles%\Sony Ericsson\Update Service\db\
So they are decryptable using the known method.
Tampered Device Service does in fact check for Root and custom software.
Don't know if this will have an effect in the updating process from SEUS.
So, it's a bad news huh. Keep looking. Thanks for the info.
Sent from my X10i using XDA App
Confirmed that devices that has been rooted and modified in software will not be eligible for 2.3.3 update. You will have to flash back a stock unrooted firmware before updating to 2.3.3
Of course. SE said that in their blog. Better backup all data in SD Card and format it too. I don't think the SEUS' intelligent enough to check out that the SD Card contains CyanogenMod folder as busybox and xRecovery
EDIT: I tried to find the update 2.1 package in my computer after repaired my phone for several times and I can't find it. It's of course that it's deleted as soon as the update completed.
I believe SEUS works like the Flash Tool and Pay-Per-Update service through fastgsm.com and davince.
Flash Tool requires you to provide the firmware and place the sin files in the correct location.
Pay service requires a fee to install the correct sin files/firmware.
SEUS requires a CDA to determine which sin files/firmware to install.
I beg that the FlashTool works like SEUS cause without SEUS and other update services, where is FlashTool come from?
But what if SEUS change its method? Well, i still want to update and we will see how it goes.
Sent from my X10i using XDA App
Whatever method they choose, they can't close the door behind them. They need the access too. Flash Tool can be updated.
Nor would google allow that. JMHO
Yes, FT can be updated but it's development is kinda dead as of now, and we don't even have its source codes, so the other developers can't update it. Unless if Androxyde and Bin4ry want to work on FT again.
Hzu said:
Yes, FT can be updated but it's development is kinda dead as of now, and we don't even have its source codes, so the other developers can't update it. Unless if Androxyde and Bin4ry want to work on FT again.
Click to expand...
Click to collapse
Why are the devs acting like this is an issue? The Flash Tool already works on the ARC, so what are you worried about?
Work on Arc no mean it can work on X10, just like Arc has bootloader unlocked but no mean X10 can when update to 2.3.3
silveraero said:
Work on Arc no mean it can work on X10, just like Arc has bootloader unlocked but no mean X10 can when update to 2.3.3
Click to expand...
Click to collapse
You totally missed the point. The bootloader or root has NEVER mattered. When the NEVER has happened, then start your *****ing.
agentJBM said:
Why are the devs acting like this is an issue? The Flash Tool already works on the ARC, so what are you worried about?
Click to expand...
Click to collapse
What I mean is that IF SE changed their flashing method for the GB firmware and FT won't work for those who upgraded their X10 to GB. But another user has said that they won't since it requires them to start all over again.
Who knows, we're not the one who are developing the firmwares and we all should stop making assumptions(but some people aren't making assumptions, they are so sure they are right).
Hzu said:
What I mean is that IF SE changed their flashing method for the GB firmware and FT won't work for those who upgraded their X10 to GB. But another user has said that they won't since it requires them to start all over again.
Who knows, we're not the one who are developing the firmwares and we all should stop making assumptions(but some people aren't making assumptions, they are so sure they are right).
Click to expand...
Click to collapse
I am not pretending to know. However, you are failing to acknowledge that the Flash Tool is a modification of Update Service. The same method is used. Quit acting like this is nuclear science.
I told you, what IF they CHANGE the flashing method, then SEUS will also be updated with the new method.
Why am I repeating this anyway? Silly me.

[HOW-TO] Use Code Syntax Highlighting on XDA [Raise Awareness]

XDA is an awesome place for developers to share their knowledge and help each other, no question about it.
However, in my opinion, one of the flaws that prevent the app development forums from being more popular is the
Code:
tags.
Indeed, these tags do not provide syntax highlighting, and when people start pasting their whole Java class, the lack of proper indentation plus the lack of syntax highlighting leaves us with a very off-putting chunk of code, and even if you intend to help in the first place, having to go through this unreadable code can discourage many.
I was ranting about this in the [URL="http://forum.xda-developers.com/showpost.php?p=49938207&postcount=1976"]xda suggestions & feedback thread[/URL], when someone pointed-out the existence of the [B][PHP][/B] tags, which provide syntax highlighting for php, and, the syntaxes of PHP and Java being somewhat similar, they also do the trick for Java.
[FONT="Garamond"][I]Example:[/I][/FONT]
[PHP]
package com.androguide.recovery.emulator;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import android.util.Log;
public class CMDProcessor {
private final String TAG = getClass().getSimpleName();
private static final boolean DEBUG = false;
private Boolean can_su;
public SH sh;
public SH su;
public CMDProcessor() {
sh = new SH("sh");
su = new SH("su");
}
public SH suOrSH() {
return canSU() ? su : sh;
}
public boolean canSU() {
return canSU(false);
}
public class CommandResult {
private final String resultTag = TAG + '.' + getClass().getSimpleName();
public final String stdout;
public final String stderr;
public final Integer exit_value;
CommandResult(final Integer exit_value_in) {
this(exit_value_in, null, null);
}
CommandResult(final Integer exit_value_in, final String stdout_in,
final String stderr_in) {
exit_value = exit_value_in;
stdout = stdout_in;
stderr = stderr_in;
if (DEBUG)
Log.d(TAG, resultTag + "( exit_value=" + exit_value
+ ", stdout=" + stdout + ", stderr=" + stderr + " )");
}
public boolean success() {
return exit_value != null && exit_value == 0;
}
}
public class SH {
private String SHELL = "sh";
public SH(final String SHELL_in) {
SHELL = SHELL_in;
}
private String getStreamLines(final InputStream is) {
String out = null;
StringBuffer buffer = null;
final DataInputStream dis = new DataInputStream(is);
try {
if (dis.available() > 0) {
buffer = new StringBuffer(dis.readLine());
while (dis.available() > 0) {
buffer.append("\n").append(dis.readLine());
}
}
dis.close();
} catch (final Exception ex) {
Log.e(TAG, ex.getMessage());
}
if (buffer != null) {
out = buffer.toString();
}
return out;
}
public Process run(final String s) {
Process process = null;
try {
process = Runtime.getRuntime().exec(SHELL);
final DataOutputStream toProcess = new DataOutputStream(
process.getOutputStream());
toProcess.writeBytes("exec " + s + "\n");
toProcess.flush();
} catch (final Exception e) {
Log.e(TAG,
"Exception while trying to run: '" + s + "' "
+ e.getMessage());
process = null;
}
return process;
}
public CommandResult runWaitFor(final String s) {
if (DEBUG)
Log.d(TAG, "runWaitFor( " + s + " )");
final Process process = run(s);
Integer exit_value = null;
String stdout = null;
String stderr = null;
if (process != null) {
try {
exit_value = process.waitFor();
stdout = getStreamLines(process.getInputStream());
stderr = getStreamLines(process.getErrorStream());
} catch (final InterruptedException e) {
Log.e(TAG, "runWaitFor " + e.toString());
} catch (final NullPointerException e) {
Log.e(TAG, "runWaitFor " + e.toString());
}
}
return new CommandResult(exit_value, stdout, stderr);
}
}
public boolean canSU(final boolean force_check) {
if (can_su == null || force_check) {
final CommandResult r = su.runWaitFor("id");
final StringBuilder out = new StringBuilder();
if (r.stdout != null) {
out.append(r.stdout).append(" ; ");
}
if (r.stderr != null) {
out.append(r.stderr);
}
Log.d(TAG, "canSU() su[" + r.exit_value + "]: " + out);
can_su = r.success();
}
return can_su;
}
}
[/PHP]
Oddly enough, the [B][PHP][/B] tags also work for XML (while the [html] tags, that do exist, don't work):
[PHP]
<LinearLayout
android:id="@+id/contentLayout"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginLeft="8dip"
android:layout_weight="90"
android:orientation="vertical" >
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dip"
android:fontFamily="sans-serif-light"
android:textColor="#33B6EA"
android:textSize="22sp" />
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip"
android:ellipsize="end"
android:fontFamily="sans-serif-light"
android:textColor="#232323"
android:maxLines="50"
android:textSize="16sp" />
</LinearLayout>
[/PHP]
This doesn't fix the indentation issues, but as you can see, the code is much more readable and welcoming.
By using the [B][PHP][/B] tags instead of the [strike][CODE][/strike] tags, you will be more likely to get answers to your questions involving code.
[B][SIZE="3"][CENTER]So Please, for the sake of the app development forums and the eyes of your readers:
USE THE [COLOR="RoyalBlue"][PHP][/COLOR] TAGS :victory:[/CENTER][/SIZE][/B]
[CENTER][I]Please raise awareness about this, suggest people who don't use the [B][PHP][/B] tags to use them, and together we'll make this app development forum a better place than it already is :good:[/I][/CENTER]
Whoa! Never knew about this. Nice find.
Wow, this is really cool! Thanks for finding. The only problem I have with the PHP tags is on mobile, tapatalk is obviously not supporting it at all:
SimplicityApks said:
Wow, this is really cool! Thanks for finding. The only problem I have with the PHP tags is on mobile, tapatalk is obviously not supporting it at all:
Click to expand...
Click to collapse
Too bad, thanks for reporting :good:
This obviously is just a workaround, xda could quite easily implement a dedicated syntax highlighting plugin for vBulletin as I suggested in the suggestions thread, but for the time being this is probably the closest thing we've got.
Androguide.fr said:
Too bad, thanks for reporting :good:
This obviously is just a workaround, xda could quite easily implement a dedicated syntax highlighting plugin for vBulletin as I suggested in the suggestions thread, but for the time being this is probably the closest thing we've got.
Click to expand...
Click to collapse
They've got it working way better with the CODE tags: Code syntax highlighting announcement!

Help Decrypting assets

Hi, I really need help, i want to extract some .png and .jpg from the assets of the app 'Hyperdimension Neptunia The App'
after 3 month of research i found out that the assets are probably "encrypted" i wanted the textures for the live2D model files, and wanted to replace the sounds with the English versions from the iOS app that i extracted.
Audio was .caf in iOS but in Android it says its .mp3
This Line in a class says something about the audio: localEditor.putString("alarm_voice", bw.a(str, "caf", "mp3"));
The .caf opens and runs fine so whats the problem and anyone help me decrypt it? :fingers-crossed:
Full "AlarmActivity.class"
Code:
package jp.co.ideaf.neptune.nepkamijigenapp;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.TimePicker;
import java.util.Calendar;
import java.util.Timer;
import jp.co.ideaf.neptune.nepkamijigenapp.a.a;
import jp.co.ideaf.neptune.nepkamijigenapp.a.d;
import jp.co.ideaf.neptune.nepkamijigenapp.a.f;
import jp.co.ideaf.neptune.nepkamijigenapp.a.h;
import jp.co.ideaf.neptune.nepkamijigenapp.d.z;
public class AlarmActivity extends Activity
{
private a a = null;
private d b = null;
private Timer c = null;
private ee d = null;
private eg e = null;
private Handler f = new Handler();
private LinearLayout g = null;
private static int a(Context paramContext, a parama, long paramLong)
{
h localh = KamijigenApplication.c();
z localz = localh.b(parama.c().f());
int i = localh.a();
String str = localz.g();
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = Long.valueOf(paramLong / 1000L);
jp.co.ideaf.neptune.nepkamijigenapp.d.k.a(String.format("アラーム発生時間 : %d秒", arrayOfObject), new Object[0]);
f localf = new f(paramLong + Calendar.getInstance().getTimeInMillis());
SharedPreferences.Editor localEditor = paramContext.getSharedPreferences(bw.a(paramContext, 2131034117), 0).edit();
localEditor.putString("alarm_voice", bw.a(str, "caf", "mp3"));
localEditor.putBoolean("snooze", parama.b);
localEditor.putInt("snooze_time", parama.c);
localEditor.commit();
Intent localIntent = new Intent(paramContext, AlarmDialogActivity.class);
localIntent.addFlags(268435456);
PendingIntent localPendingIntent = PendingIntent.getActivity(paramContext, 0, localIntent, 0);
((AlarmManager)paramContext.getSystemService("alarm")).set(0, localf.b(), localPendingIntent);
return i;
}
private void a()
{
TimePicker localTimePicker = (TimePicker)findViewById(2131165202);
if (localTimePicker == null);
while (true)
{
return;
localTimePicker.setIs24HourView(Boolean.valueOf(true));
localTimePicker.setCurrentHour(Integer.valueOf(this.a.c().f()));
localTimePicker.setCurrentMinute(Integer.valueOf(this.a.c().g()));
}
}
private void a(int paramInt)
{
TextView localTextView = (TextView)findViewById(2131165196);
if (localTextView != null)
{
localTextView.setText(Integer.toString(paramInt));
localTextView.append(bw.a(this, 2131034215));
}
}
private void a(int paramInt1, int paramInt2)
{
TextView localTextView1 = (TextView)findViewById(2131165194);
if (localTextView1 != null)
{
localTextView1.setText(Integer.toString(paramInt1));
localTextView1.append(bw.a(this, 2131034211));
}
TextView localTextView2 = (TextView)findViewById(2131165195);
if (localTextView2 != null)
{
localTextView2.setText(Integer.toString(paramInt2));
localTextView2.append(bw.a(this, 2131034212));
}
}
public static void a(Context paramContext, a parama)
{
d locald = KamijigenApplication.a();
locald.b(paramContext, false);
c(paramContext, parama);
parama.a = true;
locald.p().a(parama);
locald.c(paramContext);
}
private void b()
{
CheckBox localCheckBox = (CheckBox)findViewById(2131165197);
if (localCheckBox != null)
{
if (KamijigenApplication.a().p().a)
break label38;
localCheckBox.setEnabled(false);
localCheckBox.setChecked(false);
}
while (true)
{
return;
label38: localCheckBox.setChecked(true);
}
}
private static void c(Context paramContext, a parama)
{
f localf1 = new f(Calendar.getInstance().getTimeInMillis());
int i = localf1.f();
int j = localf1.g();
int k;
int m;
int n;
f localf2;
long l;
if ((i < parama.c().f()) || ((i == parama.c().f()) && (j < parama.c().g())))
{
k = localf1.c();
m = localf1.d();
n = localf1.e();
localf2 = new f(k, m, n, parama.c().f(), parama.c().g(), 0);
jp.co.ideaf.neptune.nepkamijigenapp.d.k.a("targetDate : " + localf2.toString(), new Object[0]);
jp.co.ideaf.neptune.nepkamijigenapp.d.k.a("nowDate : " + localf1.toString(), new Object[0]);
l = localf2.b() - localf1.b();
if (parama.c <= 0)
break label300;
}
label300: for (parama.b = true; ; parama.b = false)
{
int i1 = a(paramContext, parama, l);
parama.c().a(k);
parama.c().b(m);
parama.c().c(n);
parama.d = i1;
return;
f localf3 = new f(86400000L + localf1.b());
k = localf3.c();
m = localf3.d();
n = localf3.e();
localf2 = new f(k, m, n, parama.c().f(), parama.c().g(), 0);
break;
}
}
public void onClickBackButton(View paramView)
{
finish();
}
public void onClickDecideButton(View paramView)
{
CheckBox localCheckBox = (CheckBox)findViewById(2131165197);
if (((RadioButton)findViewById(2131165199)).isChecked())
{
findViewById(2131165201).setVisibility(8);
findViewById(2131165203).setVisibility(0);
findViewById(2131165201).setVisibility(0);
findViewById(2131165203).setVisibility(8);
if (localCheckBox != null)
break label127;
}
while (true)
{
return;
findViewById(2131165201).setVisibility(0);
findViewById(2131165203).setVisibility(8);
findViewById(2131165201).setVisibility(8);
findViewById(2131165203).setVisibility(0);
break;
label127: d locald = KamijigenApplication.a();
if (!locald.p().a)
showDialog(0);
else if ((locald.p().a) && (localCheckBox.isChecked()))
showDialog(2);
else
showDialog(3);
}
}
public void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setRequestedOrientation(1);
setContentView(2130903041);
d locald = KamijigenApplication.a();
this.a = new a();
this.a.a(locald.p());
a(this.a.c().f(), this.a.c().g());
a();
b();
TimePicker localTimePicker = (TimePicker)findViewById(2131165202);
if (localTimePicker != null)
{
localTimePicker.setVisibility(0);
localTimePicker.setOnTimeChangedListener(new j(this));
}
userNumberPicker localuserNumberPicker = (userNumberPicker)findViewById(2131165204);
a(this.a.c);
if ((Build.VERSION.SDK_INT < 11) && (localuserNumberPicker != null))
{
localuserNumberPicker.a(0, 59);
localuserNumberPicker.a(this.a.c);
localuserNumberPicker.a(new l(this));
}
if (Build.VERSION.SDK_INT >= 11)
{
FrameLayout localFrameLayout = (FrameLayout)findViewById(2131165203);
localuserNumberPicker.setEnabled(false);
localuserNumberPicker.setVisibility(8);
this.g = new LinearLayout(this);
this.g.setOrientation(0);
NumberPicker localNumberPicker = new NumberPicker(this);
localNumberPicker.setMinValue(0);
localNumberPicker.setMaxValue(59);
localNumberPicker.setValue(this.a.c);
localNumberPicker.setOnValueChangedListener(new m(this));
this.g.addView(localNumberPicker, 0, new LinearLayout.LayoutParams(-2, -2, 1.0F));
localFrameLayout.addView(this.g, new FrameLayout.LayoutParams(-2, -2, 17));
}
findViewById(2131165201).setVisibility(0);
findViewById(2131165203).setVisibility(8);
((RadioGroup)findViewById(2131165198)).setOnCheckedChangeListener(new n(this));
this.b = KamijigenApplication.a();
String str = getResources().getText(2131034115).toString();
LinearLayout localLinearLayout = (LinearLayout)findViewById(2131165191);
Button localButton = (Button)findViewById(2131165205);
if (str.equals(this.b.d(this.b.k())))
{
localLinearLayout.setBackgroundResource(2130837540);
localButton.setBackgroundResource(2130837513);
}
while (true)
{
if (locald.p().a)
showDialog(4);
return;
localLinearLayout.setBackgroundResource(2130837541);
localButton.setBackgroundResource(2130837514);
}
}
protected Dialog onCreateDialog(int paramInt)
{
AlertDialog localAlertDialog;
if (paramInt == 0)
localAlertDialog = new AlertDialog.Builder(this).setTitle(2131034216).setMessage(2131034217).setPositiveButton(2131034218, new q(this)).setNegativeButton(2131034219, null).create();
while (true)
{
return localAlertDialog;
if (paramInt == 1)
{
localAlertDialog = new AlertDialog.Builder(this).setMessage(2131034220).setPositiveButton(2131034221, new r(this)).create();
}
else if (paramInt == 2)
{
localAlertDialog = new AlertDialog.Builder(this).setTitle(2131034222).setMessage(2131034223).setPositiveButton(2131034224, new s(this)).setNegativeButton(2131034225, null).create();
}
else if (paramInt == 3)
{
localAlertDialog = new AlertDialog.Builder(this).setTitle(2131034226).setMessage(2131034227).setPositiveButton(2131034228, new t(this)).setNegativeButton(2131034229, null).create();
}
else
{
localAlertDialog = null;
if (paramInt == 4)
localAlertDialog = new AlertDialog.Builder(this).setMessage(2131034304).setPositiveButton(2131034228, new k(this)).setNegativeButton(2131034229, null).create();
}
}
}
protected void onPause()
{
super.onPause();
if (this.d != null)
this.d.b();
this.c.cancel();
this.c.purge();
}
protected void onResume()
{
super.onResume();
this.d = new ee(this);
this.d.a();
this.c = new Timer(true);
this.c.scheduleAtFixedRate(new o(this), 100L, 100L);
Display localDisplay = ((WindowManager)getSystemService("window")).getDefaultDisplay();
if (localDisplay.getWidth() > localDisplay.getHeight());
for (int i = localDisplay.getHeight(); ; i = localDisplay.getWidth())
{
float f1 = i / 480.0F;
LinearLayout localLinearLayout = (LinearLayout)findViewById(2131165193);
getResources().getDrawable(2130837742);
localLinearLayout.getLayoutParams().height = ((int)(90.0F * f1));
localLinearLayout.getLayoutParams().width = ((int)(f1 * 172.0F));
localLinearLayout.requestLayout();
this.e = new eg(this, 0);
return;
}
}
}
well if it is encrypted, what type ? and if it\s something like AES CBC how do you intend to get the cypher ?
That's the problem, im kinda new to this thing so im not sure how to get the cypher and i think its AES encrypted but not 100% certain. Sorry for being a noob.

[Q] I want to fix a bug inside APK app! (A SQLiteConnection was leake)

Dear all , How are you
I have an Android application , the Developer of it chose to stop the support for it.
Any way i want to fix the bug,
I am not that expert with Java so i am seeking for help
The error that the app return when it get data from the database is :
Code:
11-14 15:42:26.420 W/SQLiteConnectionPool(15763): A SQLiteConnection object for database '/data/data/com.bookscars.src.v65/databases/AppDbStoreroot7' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
Now i did decompile the APK , search for the class who call AppDbStoreroot7 database to see what we can do for it ! and i found it,
Please note that i need to edit on the Smali code
what i need to know , where i need to put the close commad since i am not a JAVA expert
here is the code :
Code:
package com.studio.sm.root.utility;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.util.Iterator;
import java.util.Vector;
import org.json.JSONArray;
import org.json.JSONObject;
public class RootLogsStorage
{
private static final String DATABASE_NAME = "AppDbStoreroot7";
private static final int DATABASE_VERSION = 1;
public static final String TABLE_BOOKS = "books";
public static final String TABLE_CARS = "cars";
private static final String TAG = "RootLogsStorage";
private DatabaseHelper DBHelper;
private final Context context;
private SQLiteDatabase db;
private RootLogsStorage(Context paramContext)
{
this.context = paramContext;
this.DBHelper = new DatabaseHelper(this.context, null);
}
public static void clearStorage(Context paramContext)
{
RootLogsStorage localRootLogsStorage = getWritable(paramContext);
localRootLogsStorage.emptyLogTable("books");
localRootLogsStorage.emptyLogTable("cars");
localRootLogsStorage.close();
}
private boolean emptyLogTable(String paramString)
{
return this.db.delete(paramString, null, null) > 0;
}
private static String getCreateStringFor(String paramString)
{
return "create table " + paramString + " (_id integer primary key autoincrement, " + "contents text not null);";
}
private Cursor getCursorOf(String paramString)
{
Cursor localCursor = this.db.query(paramString, new String[] { "_id", "contents" }, null, null, null, null, null);
if ((localCursor == null) || (localCursor.getCount() <= 0) || (!localCursor.moveToFirst()))
{
if (localCursor != null) {
localCursor.close();
}
localCursor = null;
}
return localCursor;
}
public static RootLogsStorage getReadable(Context paramContext)
{
return new RootLogsStorage(paramContext).openToRead();
}
public static RootLogsStorage getWritable(Context paramContext)
{
return new RootLogsStorage(paramContext).openToWrite();
}
private RootLogsStorage openToRead()
throws SQLException
{
this.db = this.DBHelper.getReadableDatabase();
return this;
}
private RootLogsStorage openToWrite()
throws SQLException
{
this.db = this.DBHelper.getWritableDatabase();
return this;
}
public void close()
{
this.db.close();
this.DBHelper.close();
}
public JSONArray getLogContentsOf(String paramString)
throws Exception
{
JSONArray localJSONArray = new JSONArray();
Cursor localCursor = getCursorOf(paramString);
if (localCursor == null) {
return localJSONArray;
}
while (!localCursor.isAfterLast())
{
localJSONArray.put(new JSONObject(localCursor.getString(1)));
localCursor.moveToNext();
}
localCursor.close();
return localJSONArray;
}
public void insertLogs(String paramString, Vector<String> paramVector)
{
Log.e("RootLogsStorage INSERT", paramString + "/" + paramVector.size());
Iterator localIterator = paramVector.iterator();
for (;;)
{
if (!localIterator.hasNext()) {
return;
}
String str = (String)localIterator.next();
ContentValues localContentValues = new ContentValues();
localContentValues.put("contents", str);
this.db.insert(paramString, null, localContentValues);
}
}
private static class DatabaseHelper
extends SQLiteOpenHelper
{
private DatabaseHelper(Context paramContext)
{
super("AppDbStoreroot7", null, 1);
}
public void onCreate(SQLiteDatabase paramSQLiteDatabase)
{
paramSQLiteDatabase.execSQL(RootLogsStorage.getCreateStringFor("books"));
paramSQLiteDatabase.execSQL(RootLogsStorage.getCreateStringFor("cars"));
}
public void onUpgrade(SQLiteDatabase paramSQLiteDatabase, int paramInt1, int paramInt2) {}
}
}
Please advice where to put the close command , please note i will edit on smali !

Categories

Resources