原因是當你的class有多個或沒有constructor的時候就會有問題。你必須至少有一個constructor而且假設有多個建構子的時候必須要在建構子的宣告上面加上[JsonConstructor]
例如
[JsonConstructor]
public sample(xxx a, yyy b)
{
}
[JsonConstructor]
public sample(xxx a, yyy b)
{
}
public class PlanSource
{
public ObservableCollection PlanList = new ObservableCollection();
}
public class Plan
{
public string Name
{
set;
get;
}
public ObservableCollection- itemList=new ObservableCollection
- ();
}
public class Item
{
public string DisplayName
{
get;
set;
}
}
然後你有一個ListView,並且你想要顯示所有PlanList 裡面的Name你可以這樣設計你的ListView
然後可以在那一頁的cs檔(c#)裡面例如OnNavigatedTo 填上這段
PlanSource ps=new PlanSource();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DataContext = ps;
}
這樣可以產生什麼效果呢?
//利用performLaunchActivity()回傳一個activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward);
...
}
...
...
//launch一個activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
activity.mCalled = false;
//在這裡呼叫activity裡頭的onCreate()
mInstrumentation.callActivityOnCreate(activity, r.state);
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
...
return activity;
}
public Activity newActivity(Class clazz, Context context,
IBinder token, Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance) throws InstantiationException,
IllegalAccessException {
Activity activity = (Activity)clazz.newInstance();
ActivityThread aThread = null;
//設定一些activity的東西
activity.attach(context, aThread, this, token, application, intent,
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration());
return activity;
}
我們看一下activity.attach()
... //利用PolicyManager.makeNewWindow來產生一個window mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); ...那PolicyManager.makeNewWindow()是什麼呢?
...
static {
// Pull in the actual implementation of the policy at run-time
try {
//在run time的時候讀取
//frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java
//一個PhonePolicy
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
} catch (ClassNotFoundException ex) {
...
}
}
// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
如果我們去看Policy.java就可以發現真正的makeNewWindow了public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
回到performLaunchActivity(),他會去呼叫Activity裡面的onCreate()而在這裡面我們會利用setContentView()來設定我們的UI,接著看一下handleResumeActivity() ...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
//取得decorView
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//取得WindowManager
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//將取得的 decor加入取得的WindowManager
wm.addView(decor, l);
}
}
...
這裡有兩個地方可以看的。第一個這個decorView是什麼呢?第二個,這個WindowManager又是哪來的呢?
第一部份,r.window.getDecorView()的前面r.window是什麼呢?剛剛我們追過就是phoneWindow所以getDecorView()我們就直接看
@Override
public final View getDecorView() {
if (mDecor == null) {
installDecor();
}
return mDecor;
}
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
}
if (mContentParent == null) {
//generateLayout input是mDecor return 一個viewgroup
mContentParent = generateLayout(mDecor);
...
}
protected ViewGroup generateLayout(DecorView decor) {
...
//取得title 並加入decor中
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
//findViewById實際上是return getDecorView().findViewById(id);
//他會去尋找{@link android.app.Activity#onCreate}所定義的xml
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
...
return contentParent;
}
public final void addView(View view, ViewGroup.LayoutParams params) {
// Let this throw an exception on a bad params.
WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params;
CharSequence curTitle = wp.getTitle();
...
super.addView(view, params);
}
而LocalWindowManager 他是extends WindowManagerImpl.CompatModeWrapper, 因此我們去看一下WindowManagerImpl 的CompatModeWrapper才知道addView是寫些什麼public void addView(View view, ViewGroup.LayoutParams params) {
addView(view, params, null, false);
}
private void addView(View view, ViewGroup.LayoutParams params,
CompatibilityInfoHolder cih, boolean nest) {
...
//ViewRootImpl是我們接下來的重點
ViewRootImpl root;
View panelParentView = null;
synchronized (this) {
...
root = new ViewRootImpl(view.getContext());
root.mAddNesting = 1;
...
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
}
// do this last because it fires off messages to start doing things
//這裡的view是我們一開始addView(mDecor,l)中的mDecor
root.setView(view, wparams, panelParentView);
}
我們進入ViewRootImpl了解一下//ViewRootImpl繼承了Handler
public final class ViewRootImpl extends Handler implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
//這裡建立一個surface 的 object
private final Surface mSurface = new Surface();
//還有一個W 的object, W這個class 是繼承IWindow.stub
final W mWindow;
....
public ViewRootImpl(Context context) {
....
//初始化對
getWindowSession(context.getMainLooper());
....
mWindow = new W(this);
....
}
....
}
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
if (!mInitialized) {
try {
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
//open session透過Binder與WindowManagerService做溝通做溝通
sWindowSession = Display.getWindowManager().openSession(
imm.getClient(), imm.getInputContext());
mInitialized = true;
} catch (RemoteException e) {
}
}
return sWindowSession;
}
}
ok看完了ViewRootImpl的一些global variable及constructure之後我們回到剛剛的root.setView()
setView()@ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();//實際上就是scheduleTraversals()
...
try {
mOrigWindowType = mWindowAttributes.type;
res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
}
...
}
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
public void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
//noinspection ConstantConditions
if (ViewDebug.DEBUG_LATENCY && mLastTraversalFinishedTimeNanos != 0) {
final long now = System.nanoTime();
Log.d(TAG, "Latency: Scheduled traversal, it has been "
+ ((now - mLastTraversalFinishedTimeNanos) * 0.000001f)
+ "ms since the last traversal finished.");
}
sendEmptyMessage(DO_TRAVERSAL);
}
}
public void handleMessage(Message msg) {
switch (msg.what) {
...
case DO_TRAVERSAL:
...
performTraversals();
...
}
private void performTraversals() {
....
//取得一個surface
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
....
//從surface裡面取得一個canvas然後畫在上面再把他show到螢幕
draw(fullRedrawNeeded);
....
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
....
//透過IWindowSession與WindowManagerService溝通取得一個surface
int relayoutResult = sWindowSession.relayout(
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);
//Log.d(TAG, "<<<<<< BACK FROM relayout");
....
return relayoutResult;
}
private void draw(boolean fullRedrawNeeded) {
//mSurface是剛剛ViewRootImpl的global variable
Surface surface = mSurface;
...
if (!dirty.isEmpty() || mIsAnimating) {
Canvas canvas;
try {
int left = dirty.left;
int top = dirty.top;
int right = dirty.right;
int bottom = dirty.bottom;
....
//lock一塊canvas
canvas = surface.lockCanvas(dirty);
....
try {
....
//把東西畫到canvas上
mView.draw(canvas);
} finally {
....
}
....
}
} finally {
//把canvas show到螢幕上
surface.unlockCanvasAndPost(canvas);
}
}
....
if (animating) {
mFullRedrawNeeded = true;
scheduleTraversals();
}
}
總結一下,在這一篇我們說了 property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
...
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
int main(int argc, char** argv) {
SurfaceFlinger::publishAndJoinThreadPool();
return 0;
}
SurfaceFlinger定義在SurfaceFlinger.h,而他是繼承BinderService 定義在BinderService.h 因此,我們可以在 BinderService.h看到 publishAndJoinThreadPool()的實做spproc(ProcessState::self()); sp sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());將surfaceflinger加入service並利用
ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();進入surfaceflinger裡的
SurfaceFlinger::readyToRun()定義在Thread::_threadLoop@Threads.cpp
... self->mStatus = self->readyToRun(); ...readyToRun()會做幾件事:
GraphicPlane& plane(graphicPlane(dpy)); DisplayHardware* const hw = new DisplayHardware(this, dpy); plane.setDisplayHardware(hw);
char const * const device_template[] = {
"/dev/graphics/fb%u",
"/dev/fb%u",
0 };
與kernel做溝通. 如果是graphic的話就要看平台實做了。EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); err = selectConfigForPixelFormat(display, attribs, format, &config);
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
if (mFlags & PARTIAL_UPDATES) {
// if we have partial updates, we definitely don't need to
// preserve the backbuffer, which may be costly.
eglSurfaceAttrib(display, surface,
EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
}
if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
strcpy(property, "160");
}
} else {
/* for the emulator case, reset the dpi values too */
mDpiX = mDpiY = atoi(property);
}
mDensity = atoi(property) * (1.0f/160.0f);
context = eglCreateContext(display, config, NULL, contextAttributes);context存放著當前的 顏色,texture 等等的資訊
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
mHwc = new HWComposer(mFlinger);
if (mHwc->initCheck() == NO_ERROR) {
mHwc->setFrameBuffer(mDisplay, mSurface);
}
property_set("ctl.start", "bootanim");
在readyToRun()跑完之後,就會進入SurfaceFlinger::threadLoop()在下一篇會討論
Flag Value
|
CPU
|
Screen
|
Keyboard
|
On*
|
Off
|
Off
| |
On
|
Dim
|
Off
| |
On
|
Bright
|
Off
| |
On
|
Bright
|
Bright
|
Flag Value
|
Description
|
Normal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately.
| |
If this flag is set, the user activity timer will be reset when the WakeLock is released, causing the illumination to remain on a bit longer. This can be used to reduce flicker if you are cycling between wake lock conditions.
|
PowerManager pm =(PowerManager)mContext.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.new WakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK| PowerManager.ON_AFTER_RELEASE,TAG); wl.acquire(); // ... wl.release();
CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y
static struct gpio_led gpio_leds[] = {
{
.name = "WHITE_LED",//should change to your own
.gpio = _GPIO_1, //should change to your own
.active_low = 1,
.default_trigger = "timer",
},
};
static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
.num_leds = ARRAY_SIZE(gpio_leds),
};
static struct platform_device leds_gpio = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &gpio_led_info,
},
};
//記得要在類似init加入-->
platform_device_register(&leds_gpio);
基本上依我的板子為例,platform_driver的實做已經在driver/leds/leds-gpio.c裡面做好了 不需要更改
以我的版為例,修改的是libleds.c 在 static int open_lights(const struct hw_module_t *module, char const *name, struct hw_device_t **device) 裡面新增了 }else if(0 == strcmp(LIGHT_ID_BATTERY, name)){ set_light = set_light_battery; } 然後因為我的led是gpio led, 只支援on/off ,沒有brightness level, Android定義了不同的level會有不同的顏色或閃爍 因此我的實做為 static int set_light_battery(struct light_device_t *dev, struct light_state_t const *state) { int err = 0; int flashmode=state->flashMode; pthread_mutex_lock(&g_lock); //set flash if(flashmode==1){ err = write_str("/sys/class/leds/PMU_LED/trigger","timer"); err = write_int("/sys/class/leds/PMU_LED/delay_on",250); err = write_int("/sys/class/leds/PMU_LED/delay_off",150); }else if(state->color ==0xffffff00||state->color ==0xffff0000||state->color ==-256){ err = write_str("/sys/class/leds/PMU_LED/trigger","none"); err = write_int("/sys/class/leds/PMU_LED/brightness",0); }else if(state->color ==0xff00ff00||state->color ==0x0){ err = write_str("/sys/class/leds/PMU_LED/trigger","none"); err = write_int("/sys/class/leds/PMU_LED/brightness",255); } pthread_mutex_unlock(&g_lock); return err; }