2013年9月30日 星期一

Note of DRM

DRM:
[Game industry]
SecuROM - require authentication via online server
SafeDisc - a copy protection program for Microsoft Windows applications and games that are distributed on optical disc.It aims to restrict unauthorized disc duplication
persistent online authentication
software tampering - some interesting enough handling against possible pirated games, such as activating a invincible enemy in the game or do whatever weird or funny thing to the users.

[document]
E-DRM/ERM/IRM- prevent unauthorized use of propriestary documents.

[e-books]
Electronic books read on a personal computer or an e-book reader typically use DRM technology to limit copying, printing, and sharing of e-books. E-books are usually limited to a certain number of reading devices and some e-publishers prevent any copying or printing.

[film]
CSS(content srambling system): used by DVD forum. A encryption/decryption mechanism that requires a DVD device to equipped with the ability to decrypt in order to play it.
Windows Media DRM: Define a right management language on how a user could do with the media.
AACS(Advanced Access Content System): used by HD DVD and blueray DVD but hacked.

[music]
Each company or organization has its own DRM system and not interoperable. Sure those who adopt the same DRM system can share the content, but not on some popular players such as Apple ipods.
A suggestion is that allowing formet-shift among different DRM-protected contents should be possible in the future for users to do it privately.
However, more and more companies turn to DRM-free downloading.

[television]
broadcast flag: used to decide if a stream can be recorded.
Content Protection and Copy Management group under DVB (DVB-CPCM): not ready yet

Reference links
http://en.wikipedia.org/wiki/Digital_rights_management 
http://stackoverflow.com/questions/822468/is-there-an-open-source-drm-solution
http://www.techdirt.com/articles/20081028/0342002668.shtml
http://www.zdnet.com/blog/hardware/the-idea-of-open-source-drm-makes-me-want-to-vomit-with-rage/2844

2013年9月23日 星期一

Add command in init rc in Android

I want to run a conditional script commands during boot-up and the place to add it looks like better in init.rc or init.xxx.rc, where xxx stands for a platform name. init files have their own language and thus don't take conditional script language. Instead of directly putting those commands inside an init file, I wrote those commands in a seperate script file and call it as an service in init.rc.

(1) gemtek_prop_check.sh

#!/system/bin/sh
if [ -f /data/gemtek.prop ]
then
        /system/busybox/bin/echo "gemtek.prop found!"
else
        /system/busybox/bin/cp /gemtek_default.prop /data/gemtek.prop
        /system/busybox/bin/chmod 666 /data/gemtek.prop
        /system/busybox/bin/echo "gemtek.prop is re-generated!"
fi


- must contain  #!/system/bin/sh
- must use absolute path

(2) init.rc

service console /system/bin/sh
    class core
    console
    disabled
    user root
    group log

service gtk_prop_check /gemtek_prop_check.sh
    class core
    oneshot


- don't really know if the sequence matters, but I put it behind console service anyway.

(3) build/tools/post_process_props.py
 Where a custom prop file can be added. In my case, gemtek_default.prop is added.

(4) build/core/build/core/Makefile
Where give the command to generate gemtek_default.prop


Reference links
http://blog.csdn.net/silvervi/article/details/6315888
https://github.com/android/platform_system_core/blob/master/init/readme.txt

2013年9月17日 星期二

Check existency and write file in Android


     File file = new File(filePath);  
     if (!file.exists()){
         Log.d(TAG, "Create " + filePath);
         try {    
          file.createNewFile();
          OutputStreamWriter pswtr = new OutputStreamWriter(new FileOutputStream(file));
             for (int i= 0;i < 8; i++) {
                   pswtr.write("hotkey"+i+"=com.android.settings\n");
             }      
                pswtr.close();
         }
         catch (FileNotFoundException e) {
             Log.e(TAG , "Got exception " + e);
         }
         catch (IOException e) {
             Log.e(TAG , "Got exception " + e);
         }             
     }

2013年9月16日 星期一

[hi3716c] Add custom prop file

build/core/Makefile
Add:
(1)
# -----------------------------------------------------------------
# gemtek.prop
INSTALLED_GTK_PROP_TARGET := $(TARGET_ROOT_OUT)/gemtek_default.prop
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_GTK_PROP_TARGET)

$(INSTALLED_GTK_PROP_TARGET):
        @echo Target buildinfo: $@
        @mkdir -p $(dir $@)
        $(hide) echo "#Gemtek-defined properties" > $@;
        build/tools/post_process_props.py $@

(2)
cat $(INSTALLED_GTK_PROP_TARGET) > $(TARGET_RECOVERY_ROOT_OUT)/gemtek_default.prop

build/CleanSpec.mk
Add:
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/gemtek_default.prop)

build/tools/post_process_props.py
Add:
(1)
 Put the modifications that you need to make into the /data/gemtek.prop into this
# function. The prop object has get(name) and put(name,value) methods.
def mangle_gtk_prop(prop):
    prop.put("hotkey0", "com.android.settings")
    prop.put("hotkey1", "com.android.settings")
    prop.put("hotkey2", "com.android.settings")
    prop.put("hotkey3", "com.android.settings")
    prop.put("hotkey4", "com.android.settings")
    prop.put("hotkey5", "com.android.settings")
    prop.put("hotkey6", "com.android.settings")
    prop.put("hotkey7", "com.android.settings")

(2)
elif filename.endswith("/gemtek_default.prop"):
    mangle_gtk_prop(properties)


Then check it in init.rc and copy the gemtek_default.prop to /data if gemtek.prop doesn't exist.
gemtek.prop is the copy that user could modify on.

2013年9月12日 星期四

get/set properties in Android

I tried to use setprop/getprop shell commands to test if I could set/get a defined key to a system's permanent storage, but it didn't do that instead the key is gone after reboot. I then turned to another solution after researching the internet. I create a properties file in the data folder and read it into a Properties object. I can operate on  the object and save back the properties after finish. The following is the snippet I wrote after referring to the red link in the reference links below:

public class HotkeyListAdapter extends ArrayAdapter<Object> {
    int total_hotkey_count = 8;
    Context context;
    static String filePath = "/data/hotkey.properties";
    String hotkey_map[] = {
        "A", "B", "C", "D", "E", "F", "G", "H"
    };
    static String targetApp = "com.android.settings";   
    static String TAG = "HotkeyListAdapter";

    public HotkeyListAdapter(Context context, int resourceId) {
        super(context, resourceId);
        this.context = context;
    }

    @Override
    public int getCount() {
        return total_hotkey_count;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    static Properties loadPropties() throws IOException {
        Properties prop = new Properties();
        try {
            InputStream fileStream = new BufferedInputStream(new FileInputStream(filePath));
            prop.load(fileStream);
            fileStream.close();
        } 
     catch (FileNotFoundException e) {
            Log.e(TAG , "Got exception " + e);
        }
        return prop;
    }


    static void storePropties(Properties prop) throws IOException {
        try {
            OutputStream fileStream = new BufferedOutputStream(new FileOutputStream(filePath));
            prop.store(fileStream, "Hotkey mappings");
            fileStream.close();
        } 
     catch (FileNotFoundException e) {
            Log.e(TAG , "Got exception " + e);
        }
    }


    static String getProperties(String key) {
     Properties prop;
        try {
            prop = loadPropties();
         return prop.getProperty(key, "NA");
        }
     catch (IOException e) {
            Log.e(TAG, "Exception", e);
        }
     return "NA";
    }

    static void setProperties(String key, String value) {
     Properties prop;   
        try {
         prop = loadPropties();
         prop.setProperty(key, value);
            storePropties(prop);
        }
     catch (IOException e) {
            Log.e(TAG, "Exception", e);
        }
     return;   
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView appImage;
     TextView keyName, appName;   
     Intent hotkey_intent;
     List<ResolveInfo> resolveinfo_list;
     PackageManager pm = context.getPackageManager();
        LayoutInflater mInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.hotkey_list_row, null);    
        }   

        appImage = (ImageView) convertView.findViewById(R.id.hotkey_app_image);
     appName = (TextView) convertView.findViewById(R.id.hotkey_app_name);
     keyName = (TextView) convertView.findViewById(R.id.hotkey_name);

        /* Retrieve APP info */
     targetApp = getProperties("hotkey"+position);   
     Log.d(TAG, targetApp);
   
        hotkey_intent = new Intent("android.intent.action.MAIN");
        hotkey_intent.addCategory("android.intent.category.LAUNCHER");
     resolveinfo_list = context.getPackageManager().queryIntentActivities(hotkey_intent, 0);
        for(ResolveInfo info:resolveinfo_list){
                 if(info.activityInfo.packageName.equalsIgnoreCase(targetApp)){    
                  ApplicationInfo ai;
                     appImage.setImageDrawable(info.activityInfo.loadIcon(pm));
            try {
                         ai = pm.getApplicationInfo(info.activityInfo.packageName, 0);
                     }
            catch (final NameNotFoundException e) {
                         ai = null;
                     }
            appName.setText((ai == null ? "not found" : pm.getApplicationLabel(ai)));
            keyName.setText(hotkey_map[position]);
                     break;
                 }
        }
       
        return convertView;
    }
}


public class HotkeyAppListDialog extends DialogFragment {
    private AlertDialog mDialog;
    private static HotkeyListAdapter hotkey_list_adapter;
    private static int hotkey_num;
   
    public static HotkeyAppListDialog newInstance(int position, HotkeyListAdapter adapter) {
        HotkeyAppListDialog frag = new HotkeyAppListDialog();
     hotkey_list_adapter = adapter;
     hotkey_num = position;
        return frag;
    }
   
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
     HotkeyAppListAdapter adapter = new HotkeyAppListAdapter(getActivity(), R.layout.hotkey_app_list_row);
     ListView appList = new ListView(getActivity());   
     appList.setAdapter(adapter);
     appList.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
     appList.setOnItemClickListener(new OnItemClickListener() {   
            public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
          HotkeyListAdapter.setProperties("hotkey"+hotkey_num, (String)view.getTag());
          hotkey_list_adapter.notifyDataSetChanged();
                mDialog.cancel();
            }
        });
        builder.setView(appList);
        builder.setTitle(R.string.hotkey_app_list_title);  
     mDialog = builder.create();
        return mDialog;
    }
}


Reference links
http://stackoverflow.com/questions/14450714/how-do-i-read-a-property-from-project-properties-or-local-properties
Architecture
http://rxwen.blogspot.tw/2010/01/android-property-system.html
worth reading
http://hi.baidu.com/seucrcr/item/2b988c570cb63c9208be1778
http://bininda.com/blog/tag/android/


2013年9月11日 星期三

dump stack trace in Java

Thread.dumpStack()

Reference links
http://stackoverflow.com/questions/1069066/get-current-stack-trace-in-java

Refresh previous View from a Dialog

When returning from a Dialog, if want to refresh a previous View, say a list, the following code shows the way:

public class HotkeyAppListDialog extends DialogFragment {
    private AlertDialog mDialog;
    private static HotkeyListAdapter hotkey_list_adapter;

    public static HotkeyAppListDialog newInstance(int position, HotkeyListAdapter adapter) {
        HotkeyAppListDialog frag = new HotkeyAppListDialog();
        hotkey_list_adapter = adapter;
        return frag;
    }
   
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        HotkeyAppListAdapter adapter = new HotkeyAppListAdapter(getActivity(), R.layout.hotkey_app_list_row);
        ListView appList = new ListView(getActivity());  
        appList.setAdapter(adapter);
        appList.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        appList.setOnItemClickListener(new OnItemClickListener() {  
            public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
                Log.d("HotkeyAppListDialog", "position:"+position);
                hotkey_list_adapter.notifyDataSetChanged();
                mDialog.cancel();
            }
        });
        builder.setView(appList);
        builder.setTitle(R.string.hotkey_app_list_title);  
        mDialog = builder.create();
        return mDialog;
    }
}
 

public class HotkeySettings extends ListFragment {
    private HotkeyListAdapter hla;
   
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {                    
        View root = inflater.inflate(R.layout.hotkey_main, container, false);                    
        ListView list = (ListView) root.findViewById(android.R.id.list);
        hla = new HotkeyListAdapter(getActivity(), R.layout.hotkey_list_row);  
        hla.setNotifyOnChange(true);
        list.setAdapter(hla);
        return root;
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        DialogFragment had = HotkeyAppListDialog.newInstance(position, hla);
        had.show(getActivity().getFragmentManager(), "hotkey app list");  
    }   
}


Reference links
http://stackoverflow.com/questions/15588538/android-listfragment-does-not-refresh

Return from a Dialog to a previous View

The following code shows how to return from a popped-out dialog to a previous view:

public class HotkeyAppListDialog extends DialogFragment {
    private AlertDialog mDialog;
    private static HotkeyListAdapter hotkey_list_adapter;

    public static HotkeyAppListDialog newInstance(int position, HotkeyListAdapter adapter) {
        HotkeyAppListDialog frag = new HotkeyAppListDialog();
        hotkey_list_adapter = adapter;
        return frag;
    }
   
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
     HotkeyAppListAdapter adapter = new HotkeyAppListAdapter(getActivity(), R.layout.hotkey_app_list_row);
     ListView appList = new ListView(getActivity());   
     appList.setAdapter(adapter);
     appList.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
     appList.setOnItemClickListener(new OnItemClickListener() {   
            public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
          Log.d("HotkeyAppListDialog", "position:"+position);
          hotkey_list_adapter.notifyDataSetChanged();
                mDialog.cancel();
            }
        });
        builder.setView(appList);
        builder.setTitle(R.string.hotkey_app_list_title);  
        mDialog = builder.create();
        return mDialog;
    }
}


public class HotkeySettings extends ListFragment {
    private HotkeyListAdapter hla;
   
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {                    
        View root = inflater.inflate(R.layout.hotkey_main, container, false);                    
     ListView list = (ListView) root.findViewById(android.R.id.list);
     hla = new HotkeyListAdapter(getActivity(), R.layout.hotkey_list_row);   
     hla.setNotifyOnChange(true);
     list.setAdapter(hla);
        return root;
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        DialogFragment had = HotkeyAppListDialog.newInstance(position, hla);
        had.show(getActivity().getFragmentManager(), "hotkey app list");   
    }    
}


Reference links
http://stackoverflow.com/questions/9429550/performing-onclick-action-on-listview-inside-a-dialog-box

2013年9月10日 星期二

java.lang.IllegalStateException:The specifiedchildalready has a parent. Youmust call removeView() on the child's parent first

public class HotkeyAppListDialog extends DialogFragment {

    public static HotkeyAppListDialog newInstance(int position) {
        HotkeyAppListDialog frag = new HotkeyAppListDialog();
        return frag;
    }
   
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        HotkeyAppListAdapter adapter = new HotkeyAppListAdapter(getActivity(), R.layout.hotkey_app_list_row);
---------------------------------------------------------------------
Where causes the exception !

        View list = getActivity().getLayoutInflater().inflate(R.layout.hotkey_app_list, null);                    
        ListView appList = (ListView) list.findViewById(R.id.app_list_view);
The correct way to create a ListView instance here to avoid re-attach parent !

        ListView appList = new ListView(getActivity());    
---------------------------------------------------------------------
        appList.setAdapter(adapter);   
        builder.setView(appList);
        builder.setTitle(R.string.hotkey_app_list_title);  
        return builder.create();
    }
}

public class HotkeySettings extends ListFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {                    
        View root = inflater.inflate(R.layout.hotkey_main, container, false);                    
        ListView list = (ListView) root.findViewById(android.R.id.list);
        HotkeyListAdapter hla = new HotkeyListAdapter(getActivity(), R.layout.hotkey_list_row);   
        list.setAdapter(hla);
        return root;
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        DialogFragment had = HotkeyAppListDialog.newInstance(position);
        had.show(getActivity().getFragmentManager(), "hotkey app list");   
    }    
}

Reference links
http://stackoverflow.com/questions/13504781/custom-listview-inside-a-dialog-in-android

Use Bundle and static contructor wrapper to pass data

There's a way to define kinda a static custom constructor wrapper to pass in arguments to the real constructor :

public class HotkeyAppListDialog extends DialogFragment { 
    public static HotkeyAppListDialog newInstance(int position) {
        HotkeyAppListDialog frag = new HotkeyAppListDialog();
        Bundle args = new Bundle();
        args.putInt("position", position);
        frag.setArguments(args);
        return frag;
    }
   
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        int position = getArguments().getInt("position");   
        ...
    }
}

public class HotkeySettings extends ListFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {                    
...
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        DialogFragment had = HotkeyAppListDialog.newInstance(position);
        had.show(getActivity().getFragmentManager(), "hotkey app list");   
    }    
}