You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
4.1 KiB

(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
module L = Logging
module F = Format
(** Android lifecycle types and their lifecycle methods that are called by the framework *)
let on_destroy = "onDestroy"
let on_destroy_view = "onDestroyView"
(** return true if [pname] is a special lifecycle cleanup method *)
let is_destroy_method pname =
match pname with
| Typ.Procname.Java pname_java ->
let method_name = Typ.Procname.java_get_method pname_java in
String.equal method_name on_destroy
|| String.equal method_name on_destroy_view
| _ ->
false
let android_lifecycles =
let android_content = "android.content" in
let android_app = "android.app" in
let fragment_lifecycle =
["onInflate"; "onAttach"; "onCreate"; "onCreateView"; "onViewCreated"; "onActivityCreated";
"onViewStateRestored"; "onStart"; "onResume"; "onPause"; "onSaveInstanceState"; "onStop";
on_destroy_view; on_destroy; "onDetach"] in
[ (android_content,
"ContentProvider",
["onCreate"]);
(android_app,
"Activity",
["onCreate"; "onStart"; "onRestoreInstanceState"; "onPostCreate"; "onResume"; "onPostResume";
"onCreateDescription"; "onSaveInstanceState"; "onPause"; "onStop"; on_destroy]);
(android_app,
"Service",
["onCreate"; "onStart"; "onStartCommand"; "onBind"; "onUnbind"; on_destroy]);
(android_content,
"BroadcastReceiever",
["onReceive"]);
(android_app,
"Fragment",
fragment_lifecycle);
(* this is the pre-Android 3.0 Fragment type (can also be used post-3.0) *)
("android.support.v4.app",
"Fragment",
fragment_lifecycle);
]
let is_subtype_package_class tenv tname package classname =
PatternMatch.is_subtype tenv
tname (Typ.Name.Java.from_package_class package classname)
let is_context tenv tname =
is_subtype_package_class tenv tname "android.content" "Context"
let is_application tenv tname =
is_subtype_package_class tenv tname "android.app" "Application"
let is_activity tenv tname =
is_subtype_package_class tenv tname "android.app" "Activity"
let is_view tenv tname =
is_subtype_package_class tenv tname "android.view" "View"
let is_fragment tenv tname =
is_subtype_package_class tenv tname "android.app" "Fragment" ||
is_subtype_package_class tenv tname "android.support.v4.app" "Fragment"
(** return true if [class_name] is the name of a class that belong to the Android framework *)
let is_android_lib_class class_name =
let class_str = Typ.Name.name class_name in
String.is_prefix ~prefix:"android" class_str || String.is_prefix ~prefix:"com.android" class_str
(** given an Android framework type mangled string [lifecycle_typ] (e.g., android.app.Activity) and
a list of method names [lifecycle_procs_strs], get the appropriate typ and procnames *)
let get_lifecycle_for_framework_typ_opt tenv lifecycle_typ lifecycle_proc_strs =
match Tenv.lookup tenv lifecycle_typ with
| Some { methods } ->
(* TODO (t4645631): collect the procedures for which is_java is returning false *)
let lookup_proc lifecycle_proc =
List.find_exn ~f:(fun decl_proc ->
match decl_proc with
| Typ.Procname.Java decl_proc_java ->
String.equal lifecycle_proc (Typ.Procname.java_get_method decl_proc_java)
| _ ->
false
) methods in
(* convert each of the framework lifecycle proc strings to a lifecycle method procname *)
let lifecycle_procs =
List.fold ~f:(fun lifecycle_procs lifecycle_proc_str ->
try (lookup_proc lifecycle_proc_str) :: lifecycle_procs
with Not_found -> lifecycle_procs)
~init:[] lifecycle_proc_strs in
lifecycle_procs
| _ -> []
(** return the complete list of (package, lifecycle_classname, lifecycle_methods) trios *)
let get_lifecycles = android_lifecycles