/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.Map.Entry;
import com.intel.mpt.annotation.MayloonStubAnnotation;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AlarmManager;
import android.app.KeyguardManager;
import android.app.LoadedApk;
import android.app.NotificationManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageParser.NewPermissionInfo;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.util.AndroidRuntimeException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewRoot;
import android.view.Window;
import android.view.WindowManagerImpl;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
/**
* Interface to global information about an application environment. This is an
* abstract class whose implementation is provided by the Android system. It
* allows access to application-specific resources and classes, as well as
* up-calls for application-level operations such as launching activities,
* broadcasting and receiving intents, etc.
*/
public class Context {
private final static String TAG = "Context";
private final static boolean DEBUG = false;
public static Context mOuterContext;
private int mThemeResource = 0;
private Resources.Theme mTheme = null;
private IBinder mActivityToken = null;
private Resources mResources;
private AssetManager mAssets;
private PackageInfo mPackageInfo;
public static int count = 0;
public int icount = 0;
public ActivityThread mActivityThread;
public LoadedApk mReceiverInfo=new LoadedApk();
public LoadedApk mLoadedApk;
private static boolean DEBUG_PROVIDER = true;
private File mPreferencesDir;
private File mFilesDir;
private File mCacheDir;
private File mExternalFilesDir;
private File mExternalCacheDir;
/**
* Flag for use with {@link #createPackageContext}: include the application
* code with the context. This means loading code into the caller's
* process, so that {@link #getClassLoader()} can be used to instantiate
* the application's classes. Setting this flags imposes security
* restrictions on what application context you can access; if the
* requested application can not be safely loaded into your process,
* java.lang.SecurityException will be thrown. If this flag is not set,
* there will be no restrictions on the packages that can be loaded,
* but {@link #getClassLoader} will always return the default system
* class loader.
*/
public static final int CONTEXT_INCLUDE_CODE = 0x00000001;
/**
* Flag for use with {@link #createPackageContext}: ignore any security
* restrictions on the Context being requested, allowing it to always
* be loaded. For use with {@link #CONTEXT_INCLUDE_CODE} to allow code
* to be loaded into a process even when it isn't safe to do so. Use
* with extreme care!
*/
public static final int CONTEXT_IGNORE_SECURITY = 0x00000002;
/**
* Flag for use with {@link #createPackageContext}: a restricted context may
* disable specific features. For instance, a View associated with a restricted
* context would ignore particular XML attributes.
*/
public static final int CONTEXT_RESTRICTED = 0x00000004;
// static{
// try {
// //Looper.prepareMainLooper();
// mMainThread = (ActivityThread) Class.forName(
// "android.app.ActivityThread").newInstance();
// mMainThread.main("com.intel.jsdroid.provider.test");
// } catch(Exception e){
// System.out.println("Could not load mMainThread");
// }
// }
private ContentResolver mContentResolver;
/**
* Flag for {@link #bindService}: automatically create the service as long
* as the binding exists. Note that while this will create the service,
* its {@link android.app.Service#onStartCommand}
* method will still only be called due to an
* explicit call to {@link #startService}. Even without that, though,
* this still provides you with access to the service object while the
* service is created.
*
* <p>Specifying this flag also tells the system to treat the service
* as being as important as your own process -- that is, when deciding
* which process should be killed to free memory, the service will only
* be considered a candidate as long as the processes of any such bindings
* is also a candidate to be killed. This is to avoid situations where
* the service is being continually created and killed due to low memory.
*/
public static final int BIND_AUTO_CREATE = 0x0001;
/**
* Flag for {@link #bindService}: include debugging help for mismatched
* calls to unbind. When this flag is set, the callstack of the following
* {@link #unbindService} call is retained, to be printed if a later
* incorrect unbind call is made. Note that doing this requires retaining
* information about the binding that was made for the lifetime of the app,
* resulting in a leak -- this should only be used for debugging.
*/
public static final int BIND_DEBUG_UNBIND = 0x0002;
/**
* Flag for {@link #bindService}: don't allow this binding to raise
* the target service's process to the foreground scheduling priority.
* It will still be raised to the at least the same memory priority
* as the client (so that its process will not be killable in any
* situation where the client is not killable), but for CPU scheduling
* purposes it may be left in the background. This only has an impact
* in the situation where the binding client is a foreground process
* and the target service is in a background process.
*/
public static final int BIND_NOT_FOREGROUND = 0x0004;
public final Context getOuterContext() {
return mOuterContext;
}
public Context() {
this.mOuterContext = this;
count++;
icount = count;
Log.d(TAG, "Context is:"+icount);
}
private static Context createSystemContext() {
Context c = new Context();
c.init(null, Resources.getSystem(),null);
return c;
}
public void setLoadedApk(LoadedApk loadedApk) {
this.mLoadedApk = loadedApk;
}
public Context getApplicationContext() {
return (mLoadedApk != null) ?
mLoadedApk.getApplication() : mActivityThread.getApplication();
}
// TODO temporarily put it here
private static Context mSystemContext = null;
public static Context getSystemContext() {
if (mSystemContext == null) {
mSystemContext = Context.createSystemContext();
if(DEBUG_PROVIDER) Log.i(TAG, "System context is:"+mSystemContext.icount);
}
return mSystemContext;
}
// public Context createPackageContext(String packageName)
// throws NameNotFoundException {
// PackageInfo pi = ((PackageManager) Context.getSystemContext()
// .getSystemService(PACKAGE_SERVICE)).getPackageInfo(packageName,
// 0);
// if (pi != null) {
// Context c = new Context();
// c.init(pi, ((PackageManager) Context.getSystemContext()
// .getSystemService(PACKAGE_SERVICE))
// .getPackageResources(packageName));
// if (c.mResources != null)
// return c;
// }
//
// throw new NameNotFoundException("Application package " + packageName
// + " not found");
// }
/**
* global button events from screen_simple_tizen.xml
* global button is created in Window.generateLayout.
* This events support backKey and menuKey.
* @param v Button
*/
public void onKeyClick(View v) {
if (v.getId() == Window.ID_BACK_KEY) {
ViewRoot.simulateBack();
}
if (v.getId() == Window.ID_MENU_KEY) {
ViewRoot.simulateMenu();
}
}
public static void setOuterContext(Context context) {
mOuterContext = context;
}
public Context createPackageContext(String packageName,ActivityThread thread)
throws NameNotFoundException {
PackageInfo pi = ((PackageManager) Context.getSystemContext()
.getSystemService(PACKAGE_SERVICE)).getPackageInfo(packageName,
0);
if (pi != null) {
Context c = new Context();
c.init(pi, ((PackageManager) Context.getSystemContext()
.getSystemService(PACKAGE_SERVICE))
.getPackageResources(packageName),thread);
if (c.mResources != null)
return c;
}
throw new NameNotFoundException("Application package " + packageName
+ " not found");
}
public Context createPackageContext(String packageName, int flags)
throws PackageManager.NameNotFoundException {
return createPackageContext(packageName, mActivityThread);
}
// final void init(PackageInfo pi, Resources res) {
// mPackageInfo = pi;
// mResources = res;
// System.out.println("!!!!!!!!ActivityThread is not created!!!");
// }
public final void init(PackageInfo pi,Resources res,ActivityThread thread){
mPackageInfo = pi;
mResources = res;
mActivityThread = thread;
mContentResolver = new ApplicationContentResolver(this, thread);
if(DEBUG_PROVIDER){
if(mContentResolver==null){
Log.e(TAG, "!ApplicationContentResolver!NULL");
}else{
Log.d(TAG, "!ApplicationContentResolver!NOT NULL");
}
}
}
public void init(PackageInfo packageInfo,
IBinder activityToken, ActivityThread mainThread,
Resources container) {
mPackageInfo = packageInfo;
mResources = container;
mActivityThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread);
}
// final void init(Resources resources, ActivityThread mainThread) {
// mPackageInfo = null;
// mResources = resources;
// //mMainThread = mainThread;
// mContentResolver = new ApplicationContentResolver(this, mainThread);
// }
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.view.LayoutInflater} for inflating layout resources in
* this context.
*
* @see #getSystemService
* @see android.view.LayoutInflater
*/
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
public static final String ACTIVITY_SERVICE = "activity";
public static final String PACKAGE_SERVICE = "package";
public static final String ALARM_SERVICE = "alarm";
public static final String KEYGUARD_SERVICE = "keyguard";
public static final String NOTIFICATION_SERVICE = "notification";
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LOCATION_SERVICE="location";
private LayoutInflater mLayoutInflater = null;
private PackageManager mPackageManager = null;
private static ActivityManager mActivityManager = null;
private static AlarmManager mAlarmManager=null;
private static KeyguardManager mKeyguardManager=null;
private static NotificationManager mNotificationManager=null;
private static PowerManager mPowerManager=null;
private static WindowManagerImpl mWindowManager=null;
private static LocationManager mLocationManager=null;
private static final HashMap<String, SharedPreferencesJ2SImpl> sSharedPrefs =
new HashMap<String, SharedPreferencesJ2SImpl>();
/**
* Indicates whether this Context is restricted.
*
* @return True if this Context is restricted, false otherwise.
*
* @see #CONTEXT_RESTRICTED
*/
public boolean isRestricted() {
return false;
}
/**
* Set the base theme for this context. Note that this should be called
* before any views are instantiated in the Context (for example before
* calling {@link android.app.Activity#setContentView} or
* {@link android.view.LayoutInflater#inflate}).
*
* @param resid
* The style resource describing the theme.
*/
public void setTheme(int resid) {
mThemeResource = resid;
}
public Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter){
return registerReceiver(receiver, filter,null,null);
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, filter, broadcastPermission,
scheduler, this);
}
private Intent registerReceiverInternal(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
if (receiver != null) {
if (context != null) {
if (scheduler == null) {
scheduler = mActivityThread.getHandler();
}
}
}
IIntentReceiver rd=mReceiverInfo.getReceiverDispatcher(receiver, context, scheduler, true);
return mActivityManager.registerReceiver(mActivityThread.getApplicationThread(),rd, filter,broadcastPermission);
}
public void unregisterReceiver(BroadcastReceiver receiver){
IIntentReceiver rd=mReceiverInfo.getReceiverDispatcher(receiver, this, mActivityThread.getHandler(), true);
mActivityManager.unregisterReceiver(rd);
}
public final void sendBroadcast(Intent intent){
mActivityManager.broadcastIntent(
mActivityThread.getApplicationThread(), intent, null, null,
Activity.RESULT_OK, null, null, null, false, false);
}
public final void sendBroadcast(Intent intent,
String receiverPermission){
mActivityManager.broadcastIntent(
mActivityThread.getApplicationThread(), intent, null, null,
Activity.RESULT_OK, null, null, receiverPermission, false, false);
}
public final void sendOrderedBroadcast(Intent intent,
String receiverPermission) {
if (mActivityThread == null) {
mActivityThread = ActivityThread.currentActivityThread();
}
mActivityManager.broadcastIntent(
mActivityThread.getApplicationThread(), intent, null, null,
Activity.RESULT_OK, null, null, receiverPermission, true, false);
}
public final void sendOrderedBroadcast(Intent intent,
String receiverPermission, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras){
if (mActivityThread == null) {
mActivityThread = ActivityThread.currentActivityThread();
}
mActivityManager.broadcastIntent(
mActivityThread.getApplicationThread(), intent, null, null,
Activity.RESULT_OK, null, null, receiverPermission, true, false);
}
public void sendStickyBroadcast(Intent intent){
mActivityManager.broadcastIntent(
mActivityThread.getApplicationThread(), intent, null, null,
Activity.RESULT_OK, null, null, null, false, true);
}
public final void sendStickyOrderedBroadcast(Intent intent,
BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras){
mActivityManager.broadcastIntent(
mActivityThread.getApplicationThread(), intent, null, null,
Activity.RESULT_OK, null, null, null, true, true);
}
public final void removeStickyBroadcast(Intent intent){
//we don't need this now
}
/**
* Return the Theme object associated with this Context.
*/
public Resources.Theme getTheme() {
if (mTheme == null) {
if (mThemeResource == 0) {
mThemeResource = com.android.internal.R.style.Theme;
}
mTheme = mResources.newTheme();
// System.err
// .println("calling mTheme.applyStyle! This will be called multiple times ?!");
mTheme.applyStyle(mThemeResource, true);
}
return mTheme;
}
/**
* Retrieve styled attribute information in this Context's theme. See
* {@link Resources.Theme#obtainStyledAttributes(int[])}
* for more information.
*
* @see Resources.Theme#obtainStyledAttributes(int[])
*/
public final TypedArray obtainStyledAttributes(int[] attrs) {
return getTheme().obtainStyledAttributes(attrs);
}
/**
* Retrieve styled attribute information in this Context's theme. See
* {@link Resources.Theme#obtainStyledAttributes(int, int[])}
* for more information.
*
* @see Resources.Theme#obtainStyledAttributes(int, int[])
*/
public final TypedArray obtainStyledAttributes(int resid, int[] attrs) {
return getTheme().obtainStyledAttributes(resid, attrs);
}
/**
* Retrieve styled attribute information in this Context's theme. See
* {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
* for more information.
*
* @see Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
*/
public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
}
/**
* Retrieve styled attribute information in this Context's theme. See
* {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
* for more information.
*
* @see Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
*/
public final TypedArray obtainStyledAttributes(AttributeSet set,
int[] attrs, int defStyleAttr, int defStyleRes) {
return getTheme().obtainStyledAttributes(set, attrs, defStyleAttr,
defStyleRes);
}
public Resources getResources() {
return mResources;
}
public PackageManager getPackageManager() {
if (mPackageManager == null) {
mPackageManager = (PackageManager) getSystemContext().getSystemService(PACKAGE_SERVICE);
}
return mPackageManager;
}
public ActivityManager getActivityManager() {
if (mActivityManager != null) {
return mActivityManager;
}
return (mActivityManager = new ActivityManager(this));
}
public ActivityThread getActivityThread(){
if(mActivityThread != null){
return mActivityThread;
}
return (mActivityThread = new ActivityThread());
}
/**
* Return a localized, styled CharSequence from the application's package's
* default string table.
*
* @param resId Resource id for the CharSequence text
*/
public final CharSequence getText(int resId) {
return getResources().getText(resId);
}
/**
* Return a localized string from the application's package's
* default string table.
*
* @param resId Resource id for the string
*/
public final String getString(int resId) {
return getResources().getString(resId);
}
/**
* Return a localized formatted string from the application's package's
* default string table, substituting the format arguments as defined in
* {@link java.util.Formatter} and {@link java.lang.String#format}.
*
* @param resId Resource id for the format string
* @param formatArgs The format arguments that will be used for substitution.
*/
public final String getString(int resId, Object... formatArgs) {
return getResources().getString(resId, formatArgs);
}
// EMMA TODO, we need to implement this function later
public ClassLoader getClassLoader() {
return /*ClassLoader.getSystemClassLoader();*/null;
//return null;// ClassLoader.getSystemClassLoader();
}
public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
LayoutInflater inflater = mLayoutInflater;
if (inflater != null) {
return inflater;
}
mLayoutInflater = inflater = new LayoutInflater(this);
return inflater;
} else if (ACTIVITY_SERVICE.equals(name)) {
ActivityManager am = mActivityManager;
if (am != null) {
return am;
}
mActivityManager = am = new ActivityManager(this);
return am;
} else if (PACKAGE_SERVICE.equals(name)) {
PackageManager pm = mPackageManager;
if (pm != null)
return pm;
mPackageManager = pm = new PackageManager();
return pm;
} else if(ALARM_SERVICE.equals(name)){
AlarmManager am= mAlarmManager;
if (am != null) {
return am;
}
mAlarmManager = am = new AlarmManager();
return am;
}else if(KEYGUARD_SERVICE.equals(name)){
KeyguardManager km=mKeyguardManager;
if(km!=null){
return km;
}
mKeyguardManager=km=new KeyguardManager();
return km;
}else if(NOTIFICATION_SERVICE.equals(name)){
NotificationManager nm=mNotificationManager;
if(nm!=null){
return nm;
}
mNotificationManager=nm=new NotificationManager();
return nm;
}else if(POWER_SERVICE.equals(name)){
PowerManager pm=mPowerManager;
if(pm!=null){
return pm;
}
mPowerManager=pm=new PowerManager();
return pm;
}else if(WINDOW_SERVICE.equals(name)){
WindowManagerImpl wm = mWindowManager;
if(wm!=null){
return wm;
}
mWindowManager=wm=new WindowManagerImpl();
return wm;
}else if (LOCATION_SERVICE.equals(name)) {
LocationManager lm=mLocationManager;
if(lm!=null){
return lm;
}
mLocationManager=lm=new LocationManager();
return lm;
}
return null;
}
public String getPackageName() {
if (mPackageInfo != null) {
return mPackageInfo.packageName;
}
throw new RuntimeException("Not supported in system context");
}
public void startActivity(Intent intent) {
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mActivityThread.getInstrumentation().execStartActivity(
getOuterContext(), mActivityThread.getApplicationThread(), null, null, intent, -1);
}
public ComponentName startService(Intent service){
service.setAllowFds(false);
ComponentName cn = this.getActivityManager().startService(
mActivityThread.getApplicationThread(), service,
"");
if (cn != null && cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
}
return cn;
}
/**
* Request that a given application service be stopped. If the service is
* not running, nothing happens. Otherwise it is stopped. Note that calls
* to startService() are not counted -- this stops the service no matter
* how many times it was started.
*
* <p>Note that if a stopped service still has {@link ServiceConnection}
* objects bound to it with the {@link #BIND_AUTO_CREATE} set, it will
* not be destroyed until all of these bindings are removed. See
* the {@link android.app.Service} documentation for more details on a
* service's lifecycle.
*
* <p>This function will throw {@link SecurityException} if you do not
* have permission to stop the given service.
*
* @param service Description of the service to be stopped. The Intent may
* specify either an explicit component name to start, or a logical
* description (action, category, etc) to match an
* {@link IntentFilter} published by a service.
*
* @return If there is a service matching the given Intent that is already
* running, then it is stopped and true is returned; else false is returned.
*
* @throws SecurityException
*
* @see #startService
*/
public boolean stopService(Intent service){
return true;
}
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
// IServiceConnection sd;
// if (mPackageInfo != null) {
// sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
// mMainThread.getHandler(), flags);
// } else {
// throw new RuntimeException("Not supported in system context");
// }
// IBinder token = getActivityToken();
// if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
// && mPackageInfo.getApplicationInfo().targetSdkVersion
// < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// flags |= BIND_WAIVE_PRIORITY;
// }
service.setAllowFds(false);
int res = this.getActivityManager().bindService(
mActivityThread.getApplicationThread(),
service, "",
conn, flags);
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
}
public void unbindService(ServiceConnection conn) {
if (mPackageInfo != null) {
this.getActivityManager().unbindService(conn);
} else {
throw new RuntimeException("Not supported in system context");
}
}
final void setActivityToken(IBinder token) {
mActivityToken = token;
}
final IBinder getActivityToken() {
return mActivityToken;
}
/**
* File creation mode: the default mode, where the created file can only
* be accessed by the calling application (or all applications sharing the
* same user ID).
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
*/
public static final int MODE_PRIVATE = 0x0000;
/**
* File creation mode: allow all other applications to have read access
* to the created file.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_WRITEABLE
*/
public static final int MODE_WORLD_READABLE = 0x0001;
/**
* File creation mode: allow all other applications to have write access
* to the created file.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
*/
public static final int MODE_WORLD_WRITEABLE = 0x0002;
/**
* File creation mode: for use with {@link #openFileOutput}, if the file
* already exists then write data to the end of the existing file
* instead of erasing it.
* @see #openFileOutput
*/
public static final int MODE_APPEND = 0x8000;
public FileInputStream openFileInput(String name) throws FileNotFoundException{
File f = makeFilename(getFilesDir(), name);
return new FileInputStream(f);
}
private File makeFilename(File base, String name) {
if (name.indexOf(File.separatorChar) < 0) {
return new File(base, name);
}
throw new IllegalArgumentException(
"File " + name + " contains a path separator");
}
public FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException{
final boolean append = (mode&MODE_APPEND) != 0;
File f = makeFilename(getFilesDir(), name);
try {
FileOutputStream fos = new FileOutputStream(f, append);
return fos;
} catch (FileNotFoundException e) {
}
File parent = f.getParentFile();
parent.mkdir();
FileOutputStream fos = new FileOutputStream(f, append);
return fos;
}
public ContentResolver getContentResolver() {
if(mContentResolver==null){
mContentResolver = new ApplicationContentResolver(this,mActivityThread);
}
return mContentResolver;
}
public class ApplicationContentResolver extends ContentResolver {
public ApplicationContentResolver(Context context){
super(context);
if(DEBUG_PROVIDER) Log.d(TAG, "ApplicationContentResolver created 0..."+context.icount);
}
public ApplicationContentResolver(Context context, ActivityThread mainThread) {
super(context);
mMainThread = mainThread;
if(DEBUG_PROVIDER){
if(context==null){
System.out.println("context is null");
}
if(mMainThread==null){
Log.d(TAG, "mMainThread is null");
}
}
if(DEBUG_PROVIDER) Log.d(TAG, "ApplicationContentResolver create 1..."+context.icount);
}
protected ContentProvider acquireProvider(Context context, String name) {
if(DEBUG_PROVIDER) System.out.println("Context: Calling acquireProvider(Context context, String name)");
return mMainThread.acquireProvider(context, name);
}
protected void removeProvider(Context context, String name) {
mMainThread.removeExistingProvider(context, name);
}
protected ContentProvider acquireExistingProvider(Context context, String name) {
return mMainThread.acquireExistingProvider(context, name);
}
public boolean releaseProvider(ContentProvider provider) {
return mMainThread.releaseProvider(provider);
}
public int data = 0;
public /*static*/ ActivityThread mMainThread;
}
public SQLiteDatabase openOrCreateDatabase(String name,
int mode, CursorFactory factory)
{
//tqi3: Pname means package name to prevent different applications have the same name database, the web SQL database's name is set as <Package_Name>+"_"+<database_name>
String Pname = getPackageName();
String path = "/data/data/"+Pname + "/data/" + name;
SQLiteDatabase sqlitedatabase = SQLiteDatabase.openOrCreateDatabase(path, factory);
return sqlitedatabase;
}
// There is no way to enumerate or delete the databases available for an origin from this API in web database.
public boolean deleteDatabase(String name)
{
return false;
}
private File getDataDirFile() {
// if (mPackageInfo != null) {
// return mPackageInfo.getDataDirFile();
// }
if(mActivityThread!=null){
return new File(mActivityThread.currentPackageName());
}
throw new RuntimeException("Not supported in system context");
}
public File getFilesDir() throws RuntimeException {
if (mFilesDir == null) {
mFilesDir = new File(getDataDirFile(), "files");
}
if (!mFilesDir.exists()) {
if(!mFilesDir.mkdirs()) {
return null;
}
}
return mFilesDir;
}
public File getCacheDir() {
if (mCacheDir == null) {
mCacheDir = new File(getDataDirFile(), "cache");
}
if (!mCacheDir.exists()) {
if (!mCacheDir.mkdirs()) {
Log.w(TAG, "Unable to create cache directory");
return null;
}
FileUtils.setPermissions(mCacheDir.getPath(), FileUtils.S_IRWXU
| FileUtils.S_IRWXG | FileUtils.S_IXOTH, -1, -1);
}
return mCacheDir;
}
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesJ2SImpl sp;
//File prefsFile;
boolean needInitialLoad = false;
synchronized (sSharedPrefs) {
//use package as prefix
name = getPackageName() + name;
sp = sSharedPrefs.get(name);
if (sp != null && !sp.hasFileChangedUnexpectedly()) {
return sp;
}
//prefsFile = new File(name);
if (sp == null) {
sp = new SharedPreferencesJ2SImpl(name, mode, null);
sSharedPrefs.put(name, sp);
needInitialLoad = true;
}
}
synchronized (sp) {
if (needInitialLoad && sp.isLoaded()) {
// lost the race to load; another thread handled it
return sp;
}
// File backup = makeBackupFile(prefsFile);
// if (backup.exists()) {
// prefsFile.delete();
// backup.renameTo(prefsFile);
// }
// Debugging
//if (prefsFile.exists() && !prefsFile.canRead()) {
// Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
//}
// Map map = null;
// FileStatus stat = new FileStatus();
// if (FileUtils.getFileStatus(prefsFile.getPath(), stat) && prefsFile.canRead()) {
// try {
// FileInputStream str = new FileInputStream(prefsFile);
// map = XmlUtils.readMapXml(str);
// str.close();
// } catch (org.xmlpull.v1.XmlPullParserException e) {
// Log.w(TAG, "getSharedPreferences", e);
// } catch (FileNotFoundException e) {
// Log.w(TAG, "getSharedPreferences", e);
// } catch (IOException e) {
// Log.w(TAG, "getSharedPreferences", e);
// }
// }
// sp.replace(map);
}
return sp;
}
/**
* j2s class implemented SharedPreferences
* */
private static final class SharedPreferencesJ2SImpl implements SharedPreferences {
private String appName;
private int mMode;
//temp data
private Map<String, Object> mMap;
private boolean mLoaded = false;
private static final Object mContent = new Object();
private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
/**
* MayLoon workaround: avoid method's args name become to a,b,c of inner class and js can't use
* the args.
*/
private Object returnVal = "";
@SuppressWarnings("unchecked")
public SharedPreferencesJ2SImpl(String name, int mode, Map initialContents) {
// split by '@'
appName = name + "@";
mMode = mode;
mLoaded = initialContents != null;
mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
loadData();
}
//init mMap from localStorage by appName
private void loadData() {
/**
* @j2sNative
* var size = localStorage.length;
* for (var i = 0; i < size; i++) {
* var key = localStorage.key(i);
* if (key.indexOf(this.appName) == 0) {
* var val = localStorage.getItem(key);
* key = key.substr(this.appName.length);
* this.mMap.put(key, val);
* }
* }
*/{}
mLoaded = true;
}
public String getString(String key, String defValue) {
synchronized (this) {
String v = (String) mMap.get(key);
return v != null ? v : defValue;
}
}
public int getInt(String key, int defValue) {
synchronized (this) {
Integer v = (Integer)mMap.get(key);
if (v != null) {
this.returnVal = v;
/**
* @j2sNative
* return Number(this.returnVal);
*/{}
}
return v != null ? v : defValue;
}
}
public long getLong(String key, long defValue) {
synchronized (this) {
Long v = (Long) mMap.get(key);
if (v != null) {
this.returnVal = v;
/**
* @j2sNative
* return Number(this.returnVal);
*/{}
}
return v != null ? v : defValue;
}
}
public float getFloat(String key, float defValue) {
synchronized (this) {
Float v = (Float) mMap.get(key);
if (v != null) {
this.returnVal = v;
/**
* @j2sNative
* return Number(this.returnVal);
*/{}
}
return v != null ? v : defValue;
}
}
public boolean getBoolean(String key, boolean defValue) {
synchronized (this) {
Boolean v = (Boolean) mMap.get(key);
if (v != null) {
String strV = v.toString();
if ("true".equals(strV)) {
return true;
}
if ("false".equals(strV)) {
return false;
}
}
return defValue;
}
}
public boolean contains(String key) {
synchronized (this) {
return mMap.containsKey(key);
}
}
public Editor edit() {
return new EditorImpl();
}
public final class EditorImpl implements Editor {
private final Map<String, Object> mModified = new HashMap();
private boolean mClear = false;
/**
* MayLoon workaround: avoid method's args name become to a,b,c of inner class and js can't use
* the args.
*/
private String argKey = "";
private String argVal = "";
public Editor putString(String key, String value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putInt(String key, int value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putLong(String key, long value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putFloat(String key, float value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putBoolean(String key, boolean value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor remove(String key) {
synchronized (this) {
mModified.put(key, this);
return this;
}
}
public Editor clear() {
synchronized (this) {
mClear = true;
return this;
}
}
public void apply() {
final MemoryCommitResult mcr = commitToMemory();
// Okay to notify the listeners before it's hit disk
// because the listeners should always get the same
// SharedPreferences instance back, which has the
// changes reflected in memory.
notifyListeners(mcr);
}
public boolean commit() {
MemoryCommitResult mcr = commitToMemory();
notifyListeners(mcr);
return mcr.writeToDiskResult;
}
// Returns true if any changes were made
private MemoryCommitResult commitToMemory() {
MemoryCommitResult mcr = new MemoryCommitResult();
boolean hasListeners = mListeners.size() > 0;
if (hasListeners) {
mcr.keysModified = new ArrayList<String>();
mcr.listeners =
new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
}
synchronized (this) {
if (mClear) {
if (!mMap.isEmpty()) {
// clear the data from localStorage and mMap
Iterator<String> it = mMap.keySet().iterator();
while (it.hasNext()) {
this.argKey = appName + it.next();
/**
* @j2sNative
* localStorage.removeItem(this.argKey);
*/{}
}
mcr.changesMade = true;
mMap.clear();
}
}
mClear = false;
}
for (Entry<String, Object> e : mModified.entrySet()) {
String k = e.getKey();
Object v = e.getValue();
this.argKey = appName + k;
this.argVal = v.toString();
// remove
if (v == this) {
if (!mMap.containsKey(k)) {
continue;
}
/**
* @j2sNative
* localStorage.removeItem(this.argKey);
*/{}
mMap.remove(k);
} else {
// update or add
if (mMap.containsKey(k)) {
Object existingValue = mMap.get(k);
if (existingValue != null && existingValue.toString().equals(v.toString())) {
continue;
}
}
/**
* @j2sNative
* localStorage.setItem(this.argKey, this.argVal);
*/{}
mMap.put(k, v);
}
mcr.changesMade = true;
if (hasListeners) {
mcr.keysModified.add(k);
}
}
mModified.clear();
return mcr;
}
private void notifyListeners(final MemoryCommitResult mcr) {
if (mcr.listeners == null || mcr.keysModified == null ||
mcr.keysModified.size() == 0) {
return;
}
for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
final String key = mcr.keysModified.get(i);
for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
if (listener != null) {
listener.onSharedPreferenceChanged(SharedPreferencesJ2SImpl.this, key);
}
}
}
}
}
// Has this SharedPreferences ever had values assigned to it?
boolean isLoaded() {
synchronized (this) {
return mLoaded;
}
}
// Has the file changed out from under us? i.e. writes that
// we didn't instigate.
public boolean hasFileChangedUnexpectedly() {
return false;
}
/* package */void replace(Map newContents) {
synchronized (this) {
mLoaded = true;
if (newContents != null) {
mMap = newContents;
}
}
}
public void registerOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener) {
synchronized (this) {
mListeners.put(listener, mContent);
}
}
public void unregisterOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener) {
synchronized (this) {
mListeners.remove(listener);
}
}
public Map<String, ?> getAll() {
synchronized (this) {
return new HashMap<String, Object>(mMap);
}
}
// Return value from EditorImpl#commitToMemory()
private static class MemoryCommitResult {
public List<String> keysModified;
public Set<OnSharedPreferenceChangeListener> listeners;
public volatile boolean writeToDiskResult = true;
public boolean changesMade;
}
}
/**
* implemented SharePreferencesJ2SImpl use js's localStorage for mayloon
*/
private static final class SharedPreferencesImpl implements SharedPreferences {
// Lock ordering rules:
// - acquire SharedPreferencesImpl.this before EditorImpl.this
// - acquire mWritingToDiskLock before EditorImpl.this
private final File mFile;
// private final File mBackupFile;
private final int mMode;
private Map<String, Object> mMap; // guarded by 'this'
private int mDiskWritesInFlight = 0; // guarded by 'this'
private boolean mLoaded = false; // guarded by 'this'
private long mStatTimestamp; // guarded by 'this'
private long mStatSize; // guarded by 'this'
private final Object mWritingToDiskLock = new Object();
private static final Object mContent = new Object();
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
SharedPreferencesImpl(
File file, int mode, Map initialContents) {
mFile = file;
// mBackupFile = makeBackupFile(file);
mMode = mode;
mLoaded = initialContents != null;
mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
// FileStatus stat = new FileStatus();
mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
}
// Has this SharedPreferences ever had values assigned to it?
boolean isLoaded() {
synchronized (this) {
return mLoaded;
}
}
// Has the file changed out from under us? i.e. writes that
// we didn't instigate.
public boolean hasFileChangedUnexpectedly() {
synchronized (this) {
if (mDiskWritesInFlight > 0) {
// If we know we caused it, it's not unexpected.
if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected.");
return false;
}
}
return false;
}
/* package */ void replace(Map newContents) {
synchronized (this) {
mLoaded = true;
if (newContents != null) {
mMap = newContents;
}
}
}
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.put(listener, mContent);
}
}
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.remove(listener);
}
}
public Map<String, ?> getAll() {
synchronized(this) {
//noinspection unchecked
return new HashMap<String, Object>(mMap);
}
}
public String getString(String key, String defValue) {
synchronized (this) {
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
public int getInt(String key, int defValue) {
synchronized (this) {
Integer v = (Integer)mMap.get(key);
return v != null ? v : defValue;
}
}
public long getLong(String key, long defValue) {
synchronized (this) {
Long v = (Long)mMap.get(key);
return v != null ? v : defValue;
}
}
public float getFloat(String key, float defValue) {
synchronized (this) {
Float v = (Float)mMap.get(key);
return v != null ? v : defValue;
}
}
public boolean getBoolean(String key, boolean defValue) {
synchronized (this) {
Boolean v = (Boolean)mMap.get(key);
return v != null ? v : defValue;
}
}
public boolean contains(String key) {
synchronized (this) {
return mMap.containsKey(key);
}
}
public Editor edit() {
return new EditorImpl();
}
// Return value from EditorImpl#commitToMemory()
private static class MemoryCommitResult {
public boolean changesMade; // any keys different?
public List<String> keysModified; // may be null
public Set<OnSharedPreferenceChangeListener> listeners; // may be null
public Map<?, ?> mapToWriteToDisk;
public volatile boolean writeToDiskResult = false;
public void setDiskWriteResult(boolean result) {
writeToDiskResult = result;
}
}
public final class EditorImpl implements Editor {
private final Map<String, Object> mModified = new HashMap();
private boolean mClear = false;
public Editor putString(String key, String value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putInt(String key, int value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putLong(String key, long value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putFloat(String key, float value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putBoolean(String key, boolean value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor remove(String key) {
synchronized (this) {
mModified.put(key, this);
return this;
}
}
public Editor clear() {
synchronized (this) {
mClear = true;
return this;
}
}
public void apply() {
final MemoryCommitResult mcr = commitToMemory();
// QueuedWork.add(awaitCommit);
// Okay to notify the listeners before it's hit disk
// because the listeners should always get the same
// SharedPreferences instance back, which has the
// changes reflected in memory.
notifyListeners(mcr);
}
// Returns true if any changes were made
private MemoryCommitResult commitToMemory() {
MemoryCommitResult mcr = new MemoryCommitResult();
synchronized (SharedPreferencesImpl.this) {
// We optimistically don't make a deep copy until
// a memory commit comes in when we're already
// writing to disk.
if (mDiskWritesInFlight > 0) {
// We can't modify our mMap as a currently
// in-flight write owns it. Clone it before
// modifying it.
// noinspection unchecked
mMap = new HashMap<String, Object>(mMap);
}
mcr.mapToWriteToDisk = mMap;
mDiskWritesInFlight++;
boolean hasListeners = mListeners.size() > 0;
if (hasListeners) {
mcr.keysModified = new ArrayList<String>();
mcr.listeners =
new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
}
synchronized (this) {
if (mClear) {
if (!mMap.isEmpty()) {
mcr.changesMade = true;
mMap.clear();
}
mClear = false;
}
for (Entry<String, Object> e : mModified.entrySet()) {
String k = e.getKey();
Object v = e.getValue();
if (v == this) { // magic value for a removal mutation
if (!mMap.containsKey(k)) {
continue;
}
mMap.remove(k);
} else {
boolean isSame = false;
if (mMap.containsKey(k)) {
Object existingValue = mMap.get(k);
if (existingValue != null && existingValue.equals(v)) {
continue;
}
}
mMap.put(k, v);
}
mcr.changesMade = true;
if (hasListeners) {
mcr.keysModified.add(k);
}
}
mModified.clear();
}
}
return mcr;
}
public boolean commit() {
MemoryCommitResult mcr = commitToMemory();
SharedPreferencesImpl.this.enqueueDiskWrite(
mcr, null /* sync write on this thread okay */);
notifyListeners(mcr);
return mcr.writeToDiskResult;
}
private void notifyListeners(final MemoryCommitResult mcr) {
if (mcr.listeners == null || mcr.keysModified == null ||
mcr.keysModified.size() == 0) {
return;
}
if (Looper.myLooper() == Looper.getMainLooper()) {
for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
final String key = mcr.keysModified.get(i);
for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
if (listener != null) {
listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
}
}
}
} else {
// Run this function on the main thread.
// Context.this.mActivityThread.getHandler().post(new Runnable() {
// public void run() {
// notifyListeners(mcr);
// }
// });
}
}
}
/**
* Enqueue an already-committed-to-memory result to be written
* to disk.
*
* They will be written to disk one-at-a-time in the order
* that they're enqueued.
*
* @param postWriteRunnable if non-null, we're being called
* from apply() and this is the runnable to run after
* the write proceeds. if null (from a regular commit()),
* then we're allowed to do this disk write on the main
* thread (which in addition to reducing allocations and
* creating a background thread, this has the advantage that
* we catch them in userdebug StrictMode reports to convert
* them where possible to apply() ...)
*/
private void enqueueDiskWrite(final MemoryCommitResult mcr,
final Runnable postWriteRunnable) {
final Runnable writeToDiskRunnable = new Runnable() {
public void run() {
synchronized (mWritingToDiskLock) {
writeToFile(mcr);
}
synchronized (SharedPreferencesImpl.this) {
mDiskWritesInFlight--;
}
if (postWriteRunnable != null) {
postWriteRunnable.run();
}
}
};
final boolean isFromSyncCommit = (postWriteRunnable == null);
// Typical #commit() path with fewer allocations, doing a write on
// the current thread.
if (isFromSyncCommit) {
boolean wasEmpty = false;
synchronized (SharedPreferencesImpl.this) {
wasEmpty = mDiskWritesInFlight == 1;
}
if (wasEmpty) {
writeToDiskRunnable.run();
return;
}
}
// QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}
private static FileOutputStream createFileOutputStream(File file) {
FileOutputStream str = null;
try {
str = new FileOutputStream(file);
} catch (FileNotFoundException e) {
File parent = file.getParentFile();
if (!parent.mkdir()) {
Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
return null;
}
// FileUtils.setPermissions(
// parent.getPath(),
// FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
// -1, -1);
try {
str = new FileOutputStream(file);
} catch (FileNotFoundException e2) {
Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
}
}
return str;
}
// Note: must hold mWritingToDiskLock
private void writeToFile(MemoryCommitResult mcr) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
if (!mcr.changesMade) {
// If the file already exists, but no changes were
// made to the underlying map, it's wasteful to
// re-write the file. Return as if we wrote it
// out.
mcr.setDiskWriteResult(true);
return;
}
// if (!mBackupFile.exists()) {
// if (!mFile.renameTo(mBackupFile)) {
// Log.e(TAG, "Couldn't rename file " + mFile
// + " to backup file " + mBackupFile);
// mcr.setDiskWriteResult(false);
// return;
// }
// } else {
// mFile.delete();
// }
}
FileOutputStream str = createFileOutputStream(mFile);
if (str == null) {
mcr.setDiskWriteResult(false);
return;
}
// XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
// FileUtils.sync(str);
// str.close();
// setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
// FileStatus stat = new FileStatus();
// if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
// synchronized (this) {
// mStatTimestamp = stat.mtime;
// mStatSize = stat.size;
// }
// }
// Writing was successful, delete the backup file if there is one.
// mBackupFile.delete();
mcr.setDiskWriteResult(true);
return;
// Clean up an unsuccessfully written file
// if (mFile.exists()) {
// if (!mFile.delete()) {
// Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
// }
// }
// mcr.setDiskWriteResult(false);
}
}
/**
* @j2sNative
* console.log("Missing method: clearWallpaper");
*/
@MayloonStubAnnotation()
public void clearWallpaper() {
System.out.println("Stub" + " Function : clearWallpaper");
return;
}
/**
* @j2sNative
* console.log("Missing method: databaseList");
*/
@MayloonStubAnnotation()
public String[] databaseList() {
System.out.println("Stub" + " Function : databaseList");
return null;
}
// /**
// * @j2sNative
// * console.log("Missing method: getClassLoader");
// */
// @MayloonStubAnnotation()
// public ClassLoader getClassLoader() {
// System.out.println("Stub" + " Function : getClassLoader");
// return null;
// }
/**
* @j2sNative
* console.log("Missing method: getExternalFilesDir");
*/
@MayloonStubAnnotation()
public File getExternalFilesDir(String type) {
System.out.println("Stub" + " Function : getExternalFilesDir");
return null;
}
/**
* @j2sNative
* console.log("Missing method: getPackageCodePath");
*/
@MayloonStubAnnotation()
public String getPackageCodePath() {
System.out.println("Stub" + " Function : getPackageCodePath");
return null;
}
/**
* @j2sNative
* console.log("Missing method: fileList");
*/
@MayloonStubAnnotation()
public String[] fileList() {
System.out.println("Stub" + " Function : fileList");
return null;
}
/**
* @j2sNative
* console.log("Missing method: setWallpaper");
*/
@MayloonStubAnnotation()
public void setWallpaper(InputStream data) {
System.out.println("Stub" + " Function : setWallpaper");
return;
}
public File getFileStreamPath(String name) {
return makeFilename(getFilesDir(), name);
}
/**
* @j2sNative
* console.log("Missing method: getPackageResourcePath");
*/
@MayloonStubAnnotation()
public String getPackageResourcePath() {
System.out.println("Stub" + " Function : getPackageResourcePath");
return null;
}
/**
* @j2sNative
* console.log("Missing method: getWallpaperDesiredMinimumHeight");
*/
@MayloonStubAnnotation()
public int getWallpaperDesiredMinimumHeight() {
System.out.println("Stub" + " Function : getWallpaperDesiredMinimumHeight");
return 0;
}
/**
* @j2sNative
* console.log("Missing method: getDatabasePath");
*/
@MayloonStubAnnotation()
public File getDatabasePath(String name) {
System.out.println("Stub" + " Function : getDatabasePath");
return null;
}
/**
* @j2sNative
* console.log("Missing method: checkCallingPermission");
*/
@MayloonStubAnnotation()
public int checkCallingPermission(String permission) {
System.out.println("Stub" + " Function : checkCallingPermission");
return 0;
}
/**
* @j2sNative
* console.log("Missing method: getWallpaperDesiredMinimumWidth");
*/
@MayloonStubAnnotation()
public int getWallpaperDesiredMinimumWidth() {
System.out.println("Stub" + " Function : getWallpaperDesiredMinimumWidth");
return 0;
}
public int checkCallingOrSelfPermission(String permission) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
return checkPermission(permission, Binder.getCallingPid(),
Binder.getCallingUid());
}
public int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
return PackageManager.PERMISSION_GRANTED;
}
/**
* @j2sNative
* console.log("Missing method: getExternalCacheDir");
*/
@MayloonStubAnnotation()
public File getExternalCacheDir() {
System.out.println("Stub" + " Function : getExternalCacheDir");
return null;
}
public boolean deleteFile(String name) {
try {
File f = makeFilename(getFilesDir(), name);
if(f == null){
return true;
}
return f.delete();
} catch (RuntimeException e) {
return false;
}
}
public AssetManager getAssets() {
if(mAssets != null){
return mAssets;
}
return (mAssets = new AssetManager());
}
public Looper getMainLooper() {
if(mActivityThread == null) {
mActivityThread = ActivityThread.currentActivityThread();
}
return mActivityThread.getLooper();
}
}