Android: "Class loader may fail for processes that host multiple applications" - android

What does this message in Eclipse's logcat for Android mean?
W/ActivityThread: ClassLoader.getResources: The class loader returned by Thread.getContextClassLoader() may fail for processes that host multiple applications. You should explicitly specify a context class loader. For example: Thread.setContextClassLoader(getClass().getClassLoader());
Unfortunately, there is no context given as to this warning, so I don't know what causes this problem and how I can resolve it.

Background information
The message means that Android has setup a dummy ClassLoader with Thread.currentThread().setContextClassLoader(), and something tries to use that dummy class loader. The something can be a lot of things, it's hard to tell exactly what from the information given. There is a trick you can try though, see below. Anyway, Android sets up the dummy class loader when there is a risk that the process might contain code from more than one APK. More specifically, Android looks in your manifest if you have used android:sharedUserId:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
android:sharedUserId="triggers.dummy.loader" >
or if you run in a non-standard android:process
<application android:process="triggers.dummy.loader">
How to get rid of the warning
There are two things you can do to get rid of the warning:
Don't use android:sharedUserId or android:process
Explicitly set what APK ClassLoader to use before running any other code
To go with solution 2, there are some key insights you need. First, for any class AnyClass in an APK, AnyClass.class.getClassLoader() will return the same ClassLoader. Second,
AnyClass obj = new AnyClass();
Thread.currentThread().setContextClassLoader(obj.getClass().getClassLoader())
is the same as
Thread.currentThread().setContextClassLoader(AnyClass.class.getClassLoader())
Third, you need to call Thread.currentThread().setContextClassLoader(getClass().getClassLoader()) before the code that calls Thread.currentThread().getContextClassLoader().
Fourth, When many APKs are involved, you need to call Thread.setContextClassLoader(getClass().getClassLoader()) after the last APK has been loaded (otherwise loading the last APK will overwrite what you have set manually). Because of that, it would be a good idea to find out who is using the context class loader in you case by using the below debug trick. Then, right before that, you call Thread.setContextClassLoader(getClass().getClassLoader()) for a class from the desired APK, typically the APK that is loaded first (or, in the case when only one APK is involved, that APK ;). Fifth, the context class loader is per thread, which you need to keep in mind if your application is multi-threaded.
Debug trick
If you want to find out what code that calls ClassLoader.getResources(), this should work:
Thread.currentThread().setContextClassLoader(new ClassLoader() {
#Override
public Enumeration<URL> getResources(String resName) throws IOException {
Log.i("Debug", "Stack trace of who uses " +
"Thread.currentThread().getContextClassLoader()." +
"getResources(String resName):", new Exception());
return super.getResources(resName);
}
});
if you do this early enough, you should see in the logcat a stack trace that goes back to whoever calls getResources() on the dummy class loader.

I received this warning without either android:sharedUserId or android:process in my Manifest...
Found it only presented on an emulator...
Devices did not present the warning message. Tested on Smartphone KitKat 4.4 API 19, and Tablet 5.0.1 API 21.

Related

Obfuscating or removing string literal from all calls to Log-function in Android

We are building an Android application where we use Timber for Log-output. We have defined our own .e, .d, .v etc functions and use if (BuildConfig.DEBUG) to see if we should output the log. This takes care of the issue that we don't want to output Debug-logs in our releases but all the string literals used in our functions calls are still present in the compiled source code. We furthermore use ProGuard for obfuscation. To exemplify, in a class we can have:
somObj.normalFunction(variable)
Log.d("This secret class achieved its secret mission!");
In our release, this will not be seen in the app logs but if you reverse-engineer the APK you will see something like:
q.b(m)
z.a("This secret class achieved its secret mission!");
which can give a hint to the hackers about what class they are looking at.
So what we're looking for is to either be able to completely REMOVE all the Log function calls at compile time (using some pre-processing, annotation or something, but hopefully without having to add something before EVERY function call) OR to obfuscate all the String literal parameters to those function calls. So, two ideal solutions would be if the source, just before compilation, instead looks like:
q.b(m);
or
q.b(m);
z.a("jgasoisamgp23mmwaföfm,ak,ä")
Just by thinking I can see two bad ways to achieve this. Either we surround ALL calls to Log.d with if(BuildConfig.DEBUG) which will make the compiler remove them before compilation. But this is very tideous. OR, we make sure that every time you want to add a log-printout you need to do
Log.d(LogClass.getLog(1234))
and you then define ALL those logs inside LogClass and then remove them with if(BuildConfig.DEBUG) and return null in getLog if that's the case. But that makes it more tideous every time you want to add a log.
So finally, is there any GOOD solution to this?
DISCLAIMER: I work for PreEmptive, the company that makes PreEmptive Protection - DashO.
DashO is capable of removing calls to specific methods (e.g., Log methods). While this doesn't remove the instructions to load the string literal, just the call itself, DashO also offers String Encryption, which would offer some protection to those string literals.
As an example, I ran this class through DashO:
public class App {
public static void main(String[] args) {
Log.d("Secret message here");
}
}
After removing calls to Log.d with String Encryption on, the decompiled output looks like this:
public class App
{
public static void main(String[] paramArrayOfString)
{
a.replace("Bwpfpb7u|ih}z{?($0&", -12 - -61);
}
}
DashO offers other protections (e.g., Control Flow Obfuscation) that tend to break decompilers; I've turned those off for this demonstration.
What I would do is one or some of the following:
Use Timber (so you don't need to bother removing things or adding if statements). You simply do this once in your Application#onCreate(); if you are in DEBUG, then you plant a DebugTree that prints to the console. Else, you plant an "empty tree" that does nothing.
Simulate Timber but create your own "YourLogger" class and do the same (if you don't want to include a "third-party" library even though it's just one class). So you'd have YourLogger.v("tag", "string") and inside you'd do: if (debug) { Log.v(tag, string); } and so on and so forth for all other log types.
Use Proguard to strip the logging, and what not.
1 and 2 imply you go through your app and replace all Log. lines with either Timber. or YourLogger.
Option 3 wouldn't need that, since the code would be removed during obfuscation and the calls would do nothing, but this is mode complicated (and I haven't done it in years, don't even remember how it's done, probably easy to look it up).
I'd go for 1.
Update
Since apparently I don't know how to read, I think that in order to achieve this, your only bet is to have some sort of lookup mechanism for the actual text you want to emit/hide.
Strings.xml is the easiest, since it's included with Android and you can even localize the error messages (if that were needed, of course). Yes, there's a lookup time penalty, but I'd say unless you're iterating over thousands of items and logging different strings every time or something, the penalty wont' be noticeable (I don't have data for this, you'd have to benchmark).
Alternatively, instead of relying on resources, you could just use a file, read it, and load the strings in memory... a trade off; do you use more memory at the cost of simplicity and time to code the solution, or do you use the built-in mechanism and pay the CPU time?

MEDIA_PROJECTION_SERVICE not valid in call to getSystemService()

I am trying to develop an application that requires the ability to capture screen content. I'm targeting lollipop to avoid the requirement for root. When trying to get an instance of the MediaProjectionManager via a call to getSystemService() I am getting the following error reported in Android Studio:
Must be one of: Context.POWER_SERVICE, Context.WINDOW_SERVICE, Context.LAYOUT_INFLATER_SERVICE, Context.ACCOUNT_SERVICE, Context.ACTIVITY_SERVICE, Context.ALARM_SERVICE, Context.NOTIFICATION_SERVICE, Context.ACCESSIBILITY_SERVICE, Context.CAPTIONING_SERVICE, Context.KEYGUARD_SERVICE, Context.LOCATION_SERVICE, Context.SEARCH_SERVICE, Context.SENSOR_SERVICE, Context.STORAGE_SERVICE, Context.WALLPAPER_SERVICE, Context.VIBRATOR_SERVICE, Context.CONNECTIVITY_SERVICE, Context.WIFI_SERVICE, Context.WIFI_P2P_SERVICE, Context.NSD_SERVICE, Context.AUDIO_SERVICE, Context.MEDIA_ROUTER_SERVICE, Context.TELEPHONY_SERVICE, Context.CLIPBOARD_SERVICE, Context.INPUT_METHOD_SERVICE, Context.TEXT_SERVICES_MANAGER_SERVICE, Context.DROPBOX_SERVICE, Context.DEVICE_POLICY_SERVICE, Context.UI_MODE_SERVICE, Context.DOWNLOAD_SERVICE, Context.NFC_SERVICE, Context.BLUETOOTH_SERVICE, Context.USB_SERVICE, Context.INPUT_SERVICE, Context.DISPLAY_SERVICE, Context.USER_SERVICE, Context.PRINT_SERVICE less... (Ctrl+F1)
Reports two types of problems:
* Supplying the wrong type of resource identifier. For example, when calling Resources.getString(int id), you should be passing R.string.something, not R.drawable.something.
* Passing the wrong constant to a method which expects one of a specific set of constants. For example, when calling View#setLayoutDirection, the parameter must be android.view.View.LAYOUT_DIRECTION_LTR or android.view.View.LAYOUT_DIRECTION_RTL.
I am currently at a loss as to why this constant is not considered valid, it's there as an autocomplete option, so it's present, and it's shown in all sample code I have seen for screen capture in lollipop. I have verified that the project setup specifies Android SDK 21 as min and target. Is there something else obvious/stupid I might be missing that would cause this error?
UPDATE: Took the exact same code to Eclipse and it works without issue. So this is related to something in Android Studio specifically it seems.
I get this error while getting Context.BLUETOOTH_SERVICEand the error doc (Must be one of..) contains Context.BLUETOOTH_SERVICE though.
This is not the way Android Studio "1.2" should work. :#
Anyway, its an Inspection bug, Constant and Resource Type mismatch (How in the hell Bluetooth is a resource in android context).
You can suppress this for Class/Method/Statement, for statement, add #SuppressWarnings("ResourceType") above or before the statement.
Another approach:
Goto Settings>>Editor>>Inspection>>Android>>Constant and Resource Type Mismatches and make the severity to anything but Error, probably Warning or Weak Warning.
(Though it fixes the error issue, but I want this mismatch to be an error when it really happens.)
Run into the same problem, it is so strange, there are no any other threads talking about this problem.
Well, actually you can just ignore this error and still run the program, even with
the red marks on it

Android/Java Standard Package names are they protected

I need to make a reference to a builtin Android Java Class in NDK c++ code.
You can do it by
cls_tm = (*env)->FindClass(env, "javax/crypto/Cipher");
I am worried someone can tamper with apk, extract the java code then create their own class with the package name javax.crypto.Cipher, and read all the sensitive data I am passing to it. I am new to Java and Android so I wanted to know if it is possible to create your own package with same name as built in packages like javax.crypto.Cipher?
It is possible to create classes with the same name. However, they do not take the place of existing classes.
Every class is loaded by a class loader. Class loaders form a hierarchy, with the "bootstrap" class loader at the very top. The class loader that loads your app's classes is created by the Android app framework; it is a child of the "system" class loader, which is a child of the bootstrap loader.
When your app references a class, it asks its class loader to find it by name. Each loader will either return a class that it defined, or ask its parent to find it. (The default behavior is to ask the parent first, but an individual loader can override this.)
javax.crypto.Cipher is part of core.jar, which is loaded by the bootstrap class loader. So unless your application's class loader decides to replace Cipher with its own version, you will get the system version.
(The JNI FindClass call is actually a bit strange. Depending on where you are when you call it, it can actually end up in the system class loader rather than your app's loader. See this section in JNI Tips for an explanation.)
Suppose you really did want to replace Cipher. You can provide your own version, and your app code will happily use it. However, when you try to pass it to some other code in core.jar, your app will fail. This is because classes loaded in the VM aren't unique by name, but rather by the combination of name and class loader. So you can't pass a Cipher+MyAppLoader into something that expects a Cipher+bootstrap.
In any event, if somebody modified your APK, they would have to re-sign it; since they don't have your private key, it wouldn't look like an app that came from you.
If somebody modified a device and replaced the system Cipher with their own version, they can do whatever they want.

Unittesting AsyncTaskLoader with getLoaderResultSynchronously

I am trying to create unit tests for a REST client that does some API calls. The client works fine in the live application, but I can't get it to run in the test case.
Apparantly, LoaderTestCase.getLoaderResultSynchronously() could be used here (at least according to Android reference, but it will not accept my loader. The code:
public void testGetEventInfo() {
// Init some vars
...
// Create & execute loader
RESTLoader loader = new RESTLoader(getContext(),
RESTLoader.HTTPVerb.GET, action, params, LOADER_GET_NEWS);
getLoaderResultSynchronously(loader);
}
This yields the error getLoaderResultSynchronously(Loader) in the type LoaderTestCase is not applicable for the arguments (RESTLoader).
RESTLoader extends AsyncLoader. Note that I'm using the supportlibrary, maybe the Loader in there is incompatible? The documentation gives no information on this.
I've tried to solve this in several ways, though none seem to work:
Registered a listener to loader. However, the callback never triggers
Using CountdownLatch (also with a listener). Again, no trigger/countdown timeout.
Playing around with the type template (), without success.
Similar solutions on SO, though again failing to reach the listener.
Does anybody know why getLoaderResultSynchronously will not accept the loader? Or another clean way of testing the Loader, including a way to test return data? I can test handling the return data in a separate case, but I would also like to test the actual data.
Sincerely,
Have you taken a look at the source code? You'll find the following import statements:
import android.content.Loader;
import android.content.Loader.OnLoadCompleteListener;
It doesn't look like Android offers a support version for LoaderTestCase. The easiest solution would be to temporarily change to the non-support LoaderManager (that is, have your class make use of the android.content.Loader instead), test your app, and then switch back to the support implementation. You might also consider copying the testing source code into your project, import the support LoaderManager, and execute it directly. I'm not familiar with the test libraries for Loaders but it doesn't seem outwardly obvious that this would cause any major issues.
You can get sources from LoaderTestCase here, create SupportLoaderTestCase class from that sources in your test project and modify all namespaces to support library namespaces (e.g. change android.content.Loader with android.support.v4.content.Loader). Than you can extend your test case from SupportLoaderTestCase (not from LoaderTestCase) and use it without problems
The method you are trying to call (getLoaderResultSynchronously) accepts an object of type android.content.Loader. If your RESTLoader class is not of that EXACT type then you will get this error. I suspect your class directly or indirectly extends android.support.v4.content.Loader, which would explain the error.
I am not aware of a back-port of LoaderTestCase that would support testing of this type of class.

better way to do Debug only assert code

I am writing my first Android application and I am liberally using asserts() from junit.framework.Assert
I would like to find a way to ensure that the asserts are only compiled into the debug build, not in the release build.
I know how to query the android:debuggable attribute from the manifest so I could create a variable and accomplish this in the following fashon:
static final boolean mDebug = ...
if (mDebug)
Assert.assertNotNull(view);
Is there a better way to do this? i.e. I would prefer not to use an if() with each assert.
thanks
I think the Java language's assert keyword is likely what you want. Under the covers, the assert keyword essentially compiles into Dalvik byte code that does two things:
Checks whether the static variable assertionsDisabled (set in the class' static constructor via a call to java.lang.Class.desiredAssertionStatus()) is != 0 and if so, does nothing
If it is 0, then it checks the assertion expression and throws a java.lang.AssertionError if the expression resolves to false, effectively terminating your application.
The Dalvik runtime by default has assertions turned off, and therefore desiredAssertionStatus always returns 1 (or more precisely, some non-zero value). This is akin to running in "retail" mode. In order to turn on "debug" mode, you can run the following command against the emulator or the device:
adb shell setprop debug.assert 1
and this should do the trick (should work on the emulator or any rooted debugging-ready device).
Note however that the aforementioned Dalvik code that checks the value of assertionsDisabled and throws an AssertionError if the expression is false is always included in your byte code and liberal sprinkling of asserts in your code may lead to byte code bloat.
Please see this for a bit more detail: Can I use assert on Android devices?
If you're concerned about shipping code with the JUnit asserts in (or any other class path), you can use the ProGuard config option 'assumenosideeffects', which will strip out a class path on the assumption that removing it does nothing to the code.
Eg.
-assumenosideeffects class junit.framework.Assert {
*;
}
I have a common debug library I put all my testing methods in, and then use this option to strip it from my released apps.
This also removes the hard to spot problem of strings being manipulated that are never used in release code. For example if you write a debug log method, and in that method you check for debug mode before logging the string, you are still constructing the string, allocating memory, calling the method, but then opting to do nothing. Stripping the class out then removes the calls entirely, meaning as long as your string is constructed inside the method call, it goes away as well.
Make sure it is genuinely safe to just strip the lines out however, as it is done with no checking on ProGuard's part. Removing any void returning method will be fine, however if you are taking any return values from whatever you are removing, make sure you aren't using them for actual operational logic.
I mean if you were using a language feature, like assert(), the compiler should be able to strip that out. But this is an actual class and if a class is referenced by executable code it will be included or assumed included in the final product by the compiler.
However there is nothing stopping you from creating a script that removes all the references to the Assert class in all of your code base before compilation.
Another approach would be to make a test project that targets your application and within JUnit tests actually calls the Assert on the areas which you want to make sure work. I personally like this approach because it is a nice and clean separation of test and application.
If you are just worried about the having an if-statement everywhere, then just wrap Assert with your own class, DebuggableAssert which does that check before each call to Assert.X. It will be sort of less performant because of the method entry/exit and the conditionals but if you can maintain your code better then it might be worth it.

Categories

Resources