Cherry-pick f1dee1 from master for SDK. do not merge.

Layoutlib: add support for ITextServicesManager.

This include a fix in layoutlib_create to properly handle
delegating a static method of an inner class (was broken and
only worked on non static method).

Added a few comments here and there to *_Accessor classes so
that it's a bit more obvious what they are for and how they are
used.

Change-Id: I186ce33236e4de08d0205f75fb8d20d74c92da34
This commit is contained in:
Xavier Ducrohet
2011-09-30 18:08:05 -07:00
parent 8b42fcef5a
commit 6c465bbe80
10 changed files with 139 additions and 12 deletions

View File

@ -25,7 +25,7 @@ import android.util.AttributeSet;
import android.util.TypedValue;
/**
* Delegate used to provide new implementation of a select few methods of {@link Theme}
* Delegate used to provide new implementation of a select few methods of {@link Resources$Theme}
*
* Through the layoutlib_create tool, the original methods of Theme have been replaced
* by calls to methods of the same name in this delegate class.

View File

@ -16,6 +16,9 @@
package android.graphics;
/**
* Class allowing access to package-protected methods/fields.
*/
public class Typeface_Accessor {
public static void resetDefaults() {

View File

@ -15,6 +15,9 @@
*/
package android.os;
/**
* Class allowing access to package-protected methods/fields.
*/
public class Looper_Accessor {
public static void cleanupThread() {

View File

@ -22,6 +22,9 @@ import com.android.layoutlib.bridge.android.BridgeWindowSession;
import android.os.Handler;
import android.view.View.AttachInfo;
/**
* Class allowing access to package-protected methods/fields.
*/
public class AttachInfo_Accessor {
public static void setAttachInfo(View view) {

View File

@ -16,6 +16,9 @@
package android.view;
/**
* Class allowing access to package-protected methods/fields.
*/
public class ViewConfiguration_Accessor {
public static void clearConfigurations() {

View File

@ -16,6 +16,9 @@
package android.view.inputmethod;
/**
* Class allowing access to package-protected methods/fields.
*/
public class InputMethodManager_Accessor {
public static void resetInstance() {

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2011 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 com.android.internal.textservice;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.SpellCheckerSubtype;
/**
* Delegate used to provide new implementation of a select few methods of
* {@link ITextServicesManager$Stub}
*
* Through the layoutlib_create tool, the original methods of Stub have been replaced
* by calls to methods of the same name in this delegate class.
*
*/
public class ITextServicesManager_Stub_Delegate {
@LayoutlibDelegate
public static ITextServicesManager asInterface(IBinder obj) {
// ignore the obj and return a fake interface implementation
return new FakeTextServicesManager();
}
private static class FakeTextServicesManager implements ITextServicesManager {
public void finishSpellCheckerService(ISpellCheckerSessionListener arg0)
throws RemoteException {
// TODO Auto-generated method stub
}
public SpellCheckerInfo getCurrentSpellChecker(String arg0) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String arg0, boolean arg1)
throws RemoteException {
// TODO Auto-generated method stub
return null;
}
public SpellCheckerInfo[] getEnabledSpellCheckers() throws RemoteException {
// TODO Auto-generated method stub
return null;
}
public void getSpellCheckerService(String arg0, String arg1,
ITextServicesSessionListener arg2, ISpellCheckerSessionListener arg3, Bundle arg4)
throws RemoteException {
// TODO Auto-generated method stub
}
public boolean isSpellCheckerEnabled() throws RemoteException {
// TODO Auto-generated method stub
return false;
}
public void setCurrentSpellChecker(String arg0, String arg1) throws RemoteException {
// TODO Auto-generated method stub
}
public void setCurrentSpellCheckerSubtype(String arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
public void setSpellCheckerEnabled(boolean arg0) throws RemoteException {
// TODO Auto-generated method stub
}
public IBinder asBinder() {
// TODO Auto-generated method stub
return null;
}
}
}

View File

@ -67,6 +67,7 @@ import android.view.BridgeInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.textservice.TextServicesManager;
import java.io.File;
import java.io.FileInputStream;
@ -414,6 +415,11 @@ public final class BridgeContext extends Context {
return mBridgeInflater;
}
if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) {
// we need to return a valid service to avoid NPE
return TextServicesManager.getInstance();
}
// AutoCompleteTextView and MultiAutoCompleteTextView want a window
// service. We don't have any but it's not worth an exception.
if (WINDOW_SERVICE.equals(service)) {

View File

@ -111,7 +111,7 @@ public final class CreateInfo implements ICreateInfo {
"android.view.inputmethod.InputMethodManager#getInstance",
"android.util.Log#println_native",
"com.android.internal.util.XmlUtils#convertValueToInt",
// TODO: comment out once DelegateClass is working
"com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
};
/**

View File

@ -188,20 +188,24 @@ class DelegateMethodAdapter2 implements MethodVisitor {
boolean pushedArg0 = false;
int maxStack = 0;
// Check if the last segment of the class name has inner an class.
// Right now we only support one level of inner classes.
Type outerType = null;
int slash = mClassName.lastIndexOf('/');
int dol = mClassName.lastIndexOf('$');
if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
String outerClass = mClassName.substring(0, dol);
outerType = Type.getObjectType(outerClass);
// Change a delegate class name to "com/foo/Outer_Inner_Delegate"
delegateClassName = delegateClassName.replace('$', '_');
}
// For an instance method (e.g. non-static), push the 'this' preceded
// by the 'this' of any outer class, if any.
if (!mIsStatic) {
// Check if the last segment of the class name has inner an class.
// Right now we only support one level of inner classes.
int slash = mClassName.lastIndexOf('/');
int dol = mClassName.lastIndexOf('$');
if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
String outerClass = mClassName.substring(0, dol);
Type outerType = Type.getObjectType(outerClass);
// Change a delegate class name to "com/foo/Outer_Inner_Delegate"
delegateClassName = delegateClassName.replace('$', '_');
if (outerType != null) {
// The first-level inner class has a package-protected member called 'this$0'
// that points to the outer class.
@ -213,6 +217,7 @@ class DelegateMethodAdapter2 implements MethodVisitor {
outerType.getDescriptor()); // type of the field
maxStack++;
paramTypes.add(outerType);
}
// Push "this" for the instance method, which is always ALOAD 0